Created
December 31, 2012 09:38
-
-
Save anonymous/4418571 to your computer and use it in GitHub Desktop.
A smarter `checked` binding and `value` binding, so you can bind the checked property of a checkbox to an array of model property values, rather than a string array.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
}; | |
ko.bindingHandlers['checked'] = { | |
'init': function (element, valueAccessor, allBindingsAccessor) { | |
var updateHandler = function() { | |
var valueToWrite; | |
if (element.type == "checkbox") { | |
valueToWrite = element.checked; | |
} else if ((element.type == "radio") && (element.checked)) { | |
valueToWrite = element.value; | |
} else { | |
return; // "checked" binding only responds to checkboxes and selected radio buttons | |
} | |
var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue), | |
allBindingsValue = allBindingsAccessor(); | |
if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) { | |
// 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 = (allBindingsValue.hasOwnProperty("value") && ko.utils.unwrapObservable(allBindingsValue.value)) || element.value; | |
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); | |
} else { | |
ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true); | |
} | |
}; | |
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 }); | |
}, | |
'update': function (element, valueAccessor, allBindingsAccessor) { | |
var value = ko.utils.unwrapObservable(valueAccessor()), | |
allBindingsValue = allBindingsAccessor(); | |
if (element.type == "checkbox") { | |
if (value instanceof Array) { | |
var boundValue = (allBindingsValue.hasOwnProperty("value") && ko.utils.unwrapObservable(allBindingsValue.value)) || element.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 { | |
// When bound to anything other value (not an array), the checkbox being checked represents the value being trueish | |
element.checked = value; | |
} | |
} else if (element.type == "radio") { | |
element.checked = (element.value == value); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment