Search code examples
javascriptknockout.js

How does data bind paranthesis work in Knockout.js


I have this input and I want to change its status, so it can be readonly or editable.

<input type="text" data-bind="attr: {readonly: isViewMode || isNotEditableInvoice}, value: model.DateFormatted" />

The problem is when I don't use paranthesis for the variables.

First case: isViewMode = true, isNotEditableInvoice = false => readonly is evaluated to true

Second case: isViewMode = false, isNotEditableInvoice = true => readonly is evaluated to false

Also I have this button, and I want to show it only when the user is in edit mode.

<input type="button" value="Save" data-bind="visible: !isReadOnly || isEditableInvoice,click: onUpdate" />

I have a similar problem with using paranthesis, and I want to know what is happening there.

Third case: isReadOnly = false, isEditableInvoice = false => visible is set to false

Fourth case: When I use paranthesis for isReadOnly it's working fine, the result is the same as above, but somehow it is evaluated to true. Why isEditableInvoice is excluded from evaluation without paranthesis?

Why is this happening when I don't use paranthesis and what is the logic behind?


Solution

  • Because the knockout parser/binder is checking that you are binding against an expression ( instead lets say of a single property ) so it will evaluate the expression as-is.

    Unless you explicitly call the evaluation a.k.a add the parenthesis at the end, you are just evaluating the expression '!isReadOnly || isEditableInvoice' and the fields are not treated as observables, rather as-is.

    isReadOnly is evaluated in js terms as non-undefined, hence true.

    For example a different bind, made against a single property would be like the if/visible binds.

    You can do

    data-bind="if: model.someObservableProp"
    

    but you can not do

    data-bind="if: !model.someObservableProp"
    

    without adding the parenthesis like so:

    data-bind="if: !model.someObservableProp()"
    

    Because as soon as you add the ! operator, the parsers treats this as a js expression, not as an observable field