17

With the following code, I would expect my update function to execute every time the viewModel.item observable is updated. I can see my init and update functions firing on page load as expected, but not when my button is clicked which updates the observable's value.

Markup:

<button id='addButton'>item++</button>
<br/>
<span>viewModel.item = </span>
<span data-bind='text: $data.item(), bind: viewModel.item'></span>

Script:

$(document).ready(function() {
    $('#addButton').click(function() {
        viewModel.item(viewModel.item() + 1);
    });    
    var viewModel = {
        item: ko.observable(1)
    };        
    ko.bindingHandlers.bind = {
        init: function(element, valueAccessor) {
            alert('init');
        },
        update: function(element, valueAccessor) {
            alert('update');
        }  
    };        
    ko.applyBindings(viewModel);
}); 

I've browsed some of the similar questions and haven't found a comparable example. I've created a JSFiddle here.

Citrus
  • 756
  • 1
  • 13
  • 26

1 Answers1

32

The update function of a binding handler will run whenever the observables it accesses are updated. Your function doesn't access any observables.

Here is an updated version that will work:

ko.bindingHandlers.bind = {
    init: function(element, valueAccessor) {
        alert('init');
    },
    update: function(element, valueAccessor) {
        ko.unwrap(valueAccessor());
        alert('update');
    } 
};        

http://jsfiddle.net/vMD74/14/

Michael Best
  • 16,623
  • 1
  • 37
  • 70
  • Why call to `valueAccessor()` don't solve the problem, but `ko.unwrap(valueAccessor())` do? – it3xl Apr 10 '15 at 13:34
  • I see. The `valueAccessor()()` just works. Ok. `ko.unwrap(valueAccessor())` the only scalable solution. – it3xl Apr 10 '15 at 14:28
  • 4
    valueAccessor() just returns the value that was set to the binding (it's a computed that wraps the expression in the binding). So valueAccessor() doesn't actually access the observable, so no dependency is creatd. valueAccessor()() gets the binding's value AND accesses the observable, creating the dependency. ko.unwrap() returns a de-refernced observable or the literal object itself if the parameter to unwrap() is just a plain old object. – Chris Knoll May 09 '16 at 18:22