Skip to content

Instantly share code, notes, and snippets.

@jonesy827
Last active May 23, 2018 14:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonesy827/49b417536dd5903bbf559006c56f0b8b to your computer and use it in GitHub Desktop.
Save jonesy827/49b417536dd5903bbf559006c56f0b8b to your computer and use it in GitHub Desktop.
Knockout Select2 version 3.x binding
ko.bindingHandlers.select2 = {
init: function (el, valueAccessor, allBindingsAccessor, viewModel) {
ko.utils.domNodeDisposal.addDisposeCallback(el, function () {
$(el).select2('destroy');
});
var allBindings = allBindingsAccessor();
var valueProperty = allBindings.valueProperty || 'value';
var textProperty = allBindings.textProperty || 'text';
var isSelected = function (item) {
if (allBindings.selectedValue) {
let unwrapped = ko.unwrap(allBindings.selectedValue);
if (!unwrapped) return false;
return ko.unwrap(item[valueProperty]) == ko.unwrap(unwrapped[valueProperty]);
}
return ko.utils.arrayFilter(ko.unwrap(allBindings.selectedItems), (i) => ko.unwrap(item[valueProperty]) == ko.unwrap(i[valueProperty])).length > 0;
};
var configureSelect = function () {
var options = ko.utils.arrayMap(ko.unwrap(allBindings.selectItems), (item) => ({
id: ko.unwrap(item[valueProperty]),
text: ko.unwrap(item[textProperty]),
selected: isSelected(item)
}));
var config = ko.unwrap(allBindings.select2);
config.data = options;
config.width = '100%';
if (allBindings.selectedValue) {
$(el).select2(config);
} else {
config.templateSelection = () => 'Filtered';
let select2 = new Select2(el, config);
}
};
// Monitor source item list for changes and re-draw component if list changes
allBindings.selectItems.subscribe((newValue) => {
configureSelect();
});
configureSelect();
$(el).on('change', function (e) {
let selectData = $(el).select2('data');
if (allBindings.selectedValue) {
let selectedObject = ko.utils.arrayFilter(ko.unwrap(allBindings.selectItems), (item) => {
ko.unwrap(item[valueProperty]).toString() == selectData.id;
})[0];
allBindings.selectedValue(selectedObject);
} else {
let selectedObjects = ko.utils.arrayFilter(ko.unwrap(allBindings.selectItems), (item) => {
let v = ko.unwrap(item[valueProperty]).toString();
return ko.utils.arrayFilter(selectData, function (selectItem) {
return selectItem.id === v;
}).length > 0;
});
allBindings.selectedItems(selectedObjects);
}
});
}
};
@jonesy827
Copy link
Author

jonesy827 commented May 22, 2018

Multi-select usage:
<select data-bind="selectedItems: selected, valueProperty: 'id', textProperty: 'name', selectItems: items, select2: { placeholder: placeholder, allowClear: true }" multiple></select>

Single select usage:
<select data-bind="selectedValue: selected, valueProperty: 'id', textProperty: 'name', selectItems: items, select2: { placeholder: placeholder, allowClear: true }"></select>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment