Question

I have a custom binding that is used to re-initialise a dom element whenever a field ("Type") is changed on the viewmodel. This is defined in an update callback.

<input type="text" data-bind="value: Value, initValueField: Type()" />

ko.bindingHandlers.initValueField = {
    update:function (element, valueAccessor, allBindingsAccessor, viewModel) {
        alert('Hello World');
    }
};

See this jsFiddle for a stripped down demo.

As I understand it, one of the conditions for the update being invoked is the following:

The mechanics of custom bindings

Any time that another binding in the same data-bind attribute is triggered. This helps ensure things like the value is appropriate when the options are changed.

The issue I have is that this update callback is also called whenever the value on the viewmodel changes.

So...is it possible to either:

  1. Suppress one of the bindings from invoking the custom binding.
  2. Detect the source of the invocation inside the custom binding.
Was it helpful?

Solution

I found potential workarounds to the problem here:

Knockout.js Performance Gotcha #3 - All Bindings Fire Together

The options are:

  1. Split the bindings up by putting them onto separate elements (maybe a container element).
  2. Similar to point 1, but use containerless bindings to separate them out.
  3. Use a computed observable in the custom binding init to manage the updates manually.

OTHER TIPS

you can perhaps check for changes of the observable. And only then execute the action. Something like this:

(function () {
    var cache;
    ko.bindingHandlers.initValueField = {
        init:function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var currentValue = valueAccessor();
            cache = currentValue();
        },
        update:function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var currentValue = valueAccessor();
            if (cache !== currentValue()) {
                alert('Hello World');
                cache = currentValue();
            }
        }
    };
}());

The cache variable stores the old value of the observable. The alert is only done when the current value is different from this old one.

the working fiddle: http://jsfiddle.net/DMLzd/6/

You can use element argument in your custom binding to see the DOM element that invokes that binding. See http://jsfiddle.net/DMLzd/7/ for conditional within your custom binding which uses id attribute of textbox to decide whether to perform actions or not. I added additional textbox and button with different ID that invokes the custom binding.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top