简体   繁体   中英

knockout bind handlers update is not firing for observableArray changes

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM