kendo-labs / knockout-kendo

A project to create a robust set of Knockout.js bindings for the Kendo UI widgets.
http://kendo-labs.github.com/knockout-kendo/
273 stars 144 forks source link

The live option "enabled" does not update the widget if the observable is negated #174

Open tihoni opened 9 years ago

tihoni commented 9 years ago

In this example, the live option "enabled" is subscribed to the "enabled" observable: <input data-bind="kendoDropDownList: { [...], enabled: enabled }" /> Link: http://rniemeyer.github.io/knockout-kendo/web/DropDownList.html

However, if I invert the observable's value, the widget gets initialized correctly, but doesn't react to any further updates. <input data-bind="kendoDropDownList: { [...], enabled: !enabled() }" /> Link: https://jsfiddle.net/2ebygvyq/1/

rniemeyer commented 9 years ago

@tihoni howdy! The issue is that the binding gains its dependencies based on accessing observables. When you do !enabled() the binding receives a stack false value and no longer is able to gain a dependency on the observable. You would either want to create a flag that has the value the way that you want it or a computed that reverses it.

You could even create a little extension like:

ko.subscribable.fn.flipped = function() {
    return ko.computed({
        write: function() {
            this(!this());
        },
        read: function() {
           return !this();   
        }
    }, this);
};

You can use it like enabled: enabled.flipped()

https://jsfiddle.net/rniemeyer/quL3t1g0/

Hope that helps!

tihoni commented 9 years ago

Hey @rniemeyer ,

Thanks for this, it's a sweet workaround, I'll use this for sure!

Just out of curiosity, how did you guys handle this in knockout.js, since: <input type="text" data-bind="enable: !enabled()" /> ...works like a charm?

rniemeyer commented 9 years ago

@tihoni - In KO 3.0+, the actual binding values are not evaluated until valueAccessor() is called. This allows the bindings update function to properly capture the observable being accessed.

It is potentially possible to do this in Knockout-Kendo with KO 3+, the problem though is that we are dealing with sub-properties, so we could have something like:

kendoDropDownList: { one: !something(), two: !somethingElse() }

We would not be able to isolate the something and somethingElse dependencies, as when valueAccessor() is executed it would evaluated both. Hope that explanation was clear. Let me know if it wasn't.

IanYates commented 9 years ago

This difference in behaviour has caught me out a couple of times. Whilst technically not correct, I tend to think of the built-in KO bindings acting as though they created a computed around the binding expression. I recall reading in the KO issues list that some internal functionality may be publicly exposed in future to help make this possible (it might be that update function you describe). If sub-properties are still a problem should we avoid them in knockout-kendo and instead have ones like data-bind="kendoDropDownListOptions: blah, optionsText: 'description', optionsValue: 'id', kendoValue: value"

(using kendoValue rather than value to avoid clashing with KO's built in value) or does this not buy us anything?