Binding with && logical operator not working?

3,940 views
Skip to first unread message

Pete Davis

unread,
Feb 11, 2013, 10:27:40 AM2/11/13
to knock...@googlegroups.com
I have these 3 buttons:

        <input type="button" value="Add..." onclick="adduser()" data-bind="enable: WritePermission"/>
        <input type="button" value="Edit..." onclick="edituser()" data-bind="enable: UserSelected" />
        <input type="button" value="Edit Menu Permissions..." onclick="editmenupermissions()"  data-bind="enable: UserSelected && WritePermission" />

The default values when the form comes up are: "WritePermission" is true and "UserSelected" is false. So the "Add..." button should be the only one enabled, but the "Edit Menu Permissions..." button is also enabled.

Am I doing something wrong? The "Edit..." button is enabled properly when I set "UserSelected" to true (which happens when a row is selected from my grid).

Both WritePermission and UserSelected are in my view model as:

        self.WritePermission = ko.observable(true);
        self.UserSelected = ko.observable(false);

Thanks for any help in resolving this.

I've tried with and without parenthesis around the UserSelected && WritePermission. That doesn't seem to make a difference.

Pete Davis

unread,
Feb 11, 2013, 10:36:20 AM2/11/13
to knock...@googlegroups.com
Here's a JSFiddle that shows it:

rpn

unread,
Feb 11, 2013, 10:42:40 AM2/11/13
to knock...@googlegroups.com
Hi Pete-
If you are using observables in an expression, then you need to call each observable as a function to retrieve their value.  So, your binding would need to look like:

data-bind="enable: UserSelected() && WritePermission()"

Pete Davis

unread,
Feb 11, 2013, 11:22:48 AM2/11/13
to knock...@googlegroups.com
Thanks. That worked. Why do you have to do it that way in expressions, but not otherwise?

While I now notice this in the examples on the knockout web site, I don't see anywhere where this is explicitly explained and it seems it ought to be pointed out a bit more clearly somewhere. 

For example, on this page: http://knockoutjs.com/documentation/enable-binding.html

under the "Note: Using arbitrary JavaScript expressions" section, it doesn't say anything about it, and that seems a pretty obvious place (and it was a place I looked when I was trying to find an answer to my problem).

Thanks again.

nagas...@gmail.com

unread,
Feb 12, 2013, 6:34:49 AM2/12/13
to knock...@googlegroups.com
When knockout applies a binding it will evaluate the expression you gave it through your data-bind, and then, if it evaluates to an observable, its content is extracted to  be used and used as value for the binding. On the other hand, the expression is processed and evaluated  by the javascript engine proper, which knows nothing about knockout.

So, taking your case as example, an expression like UserSelected && WritePermission will be interpreted by javascript as a request to verify if the properties UserSelected and WritePermission on the current context ($data) are null (or any kind of false as understood by javascript) - which they are not since they contain the observable itself. The engine evaluating the expression would not even know how to extract the value inside the observable unless you explicitly tell it - i.e. by calling the observable as a function.

By the way, while not common (and not usually a good idea i would add...), it may be perfectly fine to check for the existence of an observable rather than its content, so it makes sense (IMO of course) that knockout does not try to automatically trap and unwrap every observable encountered in expressions - even not considering the intrinsic difficulty of trying to do such an operation... :)

Cris

Pete Davis

unread,
Feb 12, 2013, 5:27:38 PM2/12/13
to knock...@googlegroups.com, nagas...@gmail.com
Thanks Cris,

That makes a lot of sense. I guess, I would think, for the sake of consistency, it might make more sense for knockout to simply never try to determine if it's an observable and instead let javascript do the evaluation, unless there's some compelling reason (besides saving the 2 characters for the parenthesis) to do otherwise. I mean, I'm not suggesting it happen now and break everything, but it would avoid the inconsistency and the confusion that will inevitably cause. 

But really, my main point is, since there is an inconsistency, I think it ought to be pointed out clearly in the documentation on the site. As far as I can tell, it's not discussed on the Data-bind syntax page nor any other page that I've looked at. The examples where it's required, use it, but until it was pointed out to me, I never noticed.

nagas...@gmail.com

unread,
Feb 12, 2013, 6:35:32 PM2/12/13
to knock...@googlegroups.com, nagas...@gmail.com
While i can't tell for sure what the original intentions behind this behaviour are, i think it gets more useful the more complex and generic your view model gets, since it helps with its encapsulation - as long as you have properties that wrap your desired behaviours on the view model, you can freely change (even dynamically if needed) between mutable (observables) and immutable (simple properties) implementations, without the need to scour your entire view and change every binding by adding or removing parenthesis.

That said, i agree that the need to use parenthesis when using observables inside expressions (as opposed to them being the result of the expression) should be given a bit more relevance in the docs since it's a bit hard to figure it out until one has some familiarity with the way knockout works.
Reply all
Reply to author
Forward
0 new messages