I am trying to access multiple values through single bind handler, in case of observableArray changes which is inside the valuesAccessor binding object, the bind handler update is not firing.
ko.bindingHandlers.chosen = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
console.log("INIT");
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = ko.unwrap(valueAccessor());
ko.utils.arrayForEach(value,function(binding){
var value = ko.unwrap(binding);
});
console.log("IT WORKS!");
}
};
<select data-bind="
options: Options,
chosen: {options: Options}
"></select>
Demo: ( also on jsFiddle ):
ko.bindingHandlers.chosen = { init: function (element, valueAccessor, allBindingsAccessor, viewModel) { console.log("INIT"); }, update: function (element, valueAccessor, allBindingsAccessor, viewModel) { var value = ko.unwrap(valueAccessor()); ko.utils.arrayForEach(value,function(binding){ var value = ko.unwrap(binding); }); console.log("IT WORKS!"); } }; function Model() { this.Options = ko.observableArray(opt1); this.Reload = function () { if (!this.index) { this.Options(opt2); this.index = 1; } else { this.Options(opt1); this.index = 0; } this.Options.valueHasMutated(); }; this.index = 0; } var opt1 = [{ Text: "1", Value: "1" }, { Text: "2", Value: "2" }, ]; var opt2 = [{ Text: "3", Value: "3" }, { Text: "4", Value: "4" }, ]; ko.applyBindings(new Model());
<select data-bind=" options: Options, value: Selection, optionsText: 'Text', optionsValue: 'Value', chosen: {options: Options} "></select> <input type="button" data-bind="click: Reload" value="reload" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
The problem is that your chosen
binding isn't actually accessing the observable array, so when it mutates, knockout doesn't recall your update
handler because it doesn't think anything has changed that it's using.
With this binding:
chosen: {options: Options}
You're binding an entirely new object (with an options
property pointing at your Options
observable array). This means that when you do
var value = ko.unwrap(valueAccessor());
value
now contains: {options: <observableArrayFunction>}
- you need to actually access the options
property on it in order for knockout to register the link:
ko.utils.arrayForEach(value.options(),function(binding){
});
If you make this change, you'll see that "IT WORKS!"
is now logged when it updates. It actually gets logged twice, once because you're updating the array, and another because you're calling valueHasMutated
.
Updated snippet (with the extra valueHasMutated
removed):
ko.bindingHandlers.chosen = { init: function (element, valueAccessor, allBindingsAccessor, viewModel) { console.log("INIT"); }, update: function (element, valueAccessor, allBindingsAccessor, viewModel) { var value = ko.unwrap(valueAccessor()); ko.utils.arrayForEach(value.options(),function(binding){ var value = ko.unwrap(binding); }); console.log("IT WORKS!"); } }; function Model() { this.Options = ko.observableArray(opt1); this.Reload = function () { if (!this.index) { this.Options(opt2); this.index = 1; } else { this.Options(opt1); this.index = 0; } }; this.index = 0; } var opt1 = [{ Text: "1", Value: "1" }, { Text: "2", Value: "2" }, ]; var opt2 = [{ Text: "3", Value: "3" }, { Text: "4", Value: "4" }, ]; ko.applyBindings(new Model());
<select data-bind=" options: Options, value: Selection, optionsText: 'Text', optionsValue: 'Value', chosen: {options: Options} "></select> <input type="button" data-bind="click: Reload" value="reload" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.