Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kamranayub/4418574 to your computer and use it in GitHub Desktop.
Save kamranayub/4418574 to your computer and use it in GitHub Desktop.
A smarter `checked` and `value` binding that play nice together.
// Now you can bind your checkbox selection to an observable array of model
// properties, instead of having to bind it to a property on the item
// itself (e.g. `isSelected`).
// For more information, see:
// http://kamranicus.com/Blog/Posts/61/a-smarter-checked-binding-for-knockoutjs
// For a demo, see:
// http://jsfiddle.net/kamranayub/G8YZU
var oldValueBinding = ko.bindingHandlers['value'];
ko.bindingHandlers['value'] = {
'init': function (element, valueAccessor, allBindingsAccessor) {
// If `checked` binding is present, ignore this binding because
// user wishes to bind the checked value to the model value
var allBindings = allBindingsAccessor(),
hasChecked = allBindings.hasOwnProperty("checked");
if (hasChecked) {
return;
}
oldValueBinding['init'].apply(this, arguments);
},
'update': function (element, valueAccessor, allBindingsAccessor) {
// If `checked` binding is present, ignore this binding because
// user wishes to bind the checked value to the model value
var allBindings = allBindingsAccessor(),
hasChecked = allBindings.hasOwnProperty("checked");
if (hasChecked) {
return;
}
oldValueBinding['update'].apply(this, arguments);
}
};
var oldCheckedBinding = ko.bindingHandlers['checked'];
ko.bindingHandlers['checked'] = {
'init': function (element, valueAccessor, allBindingsAccessor) {
var allBindingsValue = allBindingsAccessor(),
modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
if (allBindingsValue.hasOwnProperty("value") && (element.type == "checkbox") && (unwrappedValue instanceof Array)) {
var updateHandler = function () {
// For checkboxes bound to an array, we add/remove the checkbox value to that array
// This works for both observable and non-observable arrays
var boundValue = ko.utils.unwrapObservable(allBindingsValue.value);
// Update values
modelValue = valueAccessor();
unwrappedValue = ko.utils.unwrapObservable(modelValue);
var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, boundValue);
if (element.checked && (existingEntryIndex < 0))
modelValue.push(boundValue);
else if ((!element.checked) && (existingEntryIndex >= 0))
modelValue.splice(existingEntryIndex, 1);
};
ko.utils.registerEventHandler(element, "click", updateHandler);
// IE 6 won't allow radio buttons to be selected unless they have a name
if ((element.type == "radio") && !element.name)
ko.bindingHandlers['uniqueName']['init'](element, function () { return true });
} else {
oldCheckedBinding['init'].apply(this, arguments);
}
},
'update': function (element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
allBindingsValue = allBindingsAccessor();
if (allBindingsValue.hasOwnProperty("value") && element.type == "checkbox" && value instanceof Array) {
var boundValue = ko.utils.unwrapObservable(allBindingsValue.value);
// When bound to an array, the checkbox being checked represents its value being present in that array
element.checked = ko.utils.arrayIndexOf(value, boundValue) >= 0;
} else {
oldCheckedBinding['update'].apply(this, arguments);
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment