I very often use the if
binding in knockout to hide something, with the added bonus that I don't need to worry about null reference errors inside the if
. In this example if address()
is null then the whole block is removed so you avoid having to deal with null checking for every property. This would not be the case had I used the visible
binding.
<div data-bind="if: address()">
You live at:
<p data-bind="text: address().street.toUpperCase()"></p>
</div>
This is the simplest case above - and yes I would generally use this pattern with the <!-- ko -->
comment syntax.
What is actually causing me problems is when I use a more complex computed
value and enable the ko.options.deferUpdates
option :
<div data-bind="if: hasAddress()">
You live at:
<p data-bind="text: address().street.toUpperCase()"></p>
</div>
The simplest implementation of this computed
observable might be something like this :
this.hasAddress = ko.computed(function () { return _this.address() != null; });
This all works great until I do the following:
1) set
ko.options.deferUpdates = true
before creating the observables.2)
address()
will start off as null and everything is fine3) set
address()
to{ street: '123 My Street' }
. Again everything works fine.4) reset
address()
to null. I get a null error becauseaddress().street
is null :-(Here is a fiddle to illustrate the problem : https://jsfiddle.net/g5gvfb7x/2/
It seems that unfortunately due to the order in which the micro-tasks runs it tries to recalculate the text
binding before the if
binding and so you still get a null error that normally wouldn't occur.
I'm a little scared about this since I use this pattern a lot :-(
Note: Using “if” and “ifnot” without a container element-- ko --> and <! -- /ko --> comments act as start/end markers, defining a “virtual element” that contains the markup inside. Knockout understands this virtual element syntax and binds as if you had a real container element.
Binding Values The binding value can be a single value, literal, a variable or can be a JavaScript expression.
A binding context is an object that holds data that you can reference from your bindings. While applying bindings, Knockout automatically creates and manages a hierarchy of binding contexts. The root level of the hierarchy refers to the viewModel parameter you supplied to ko. applyBindings(viewModel) .
Knockout is a JavaScript toolkit that allows you to connect HTML components to any data model. It is based on the MVVM paradigm and allows you to develop rich, responsive display and editor user interfaces with a clean underlying data model. Knockout. js works with a wide range of client and server-side technologies.
When using deferUpdates
, Knockout internally uses a dirty
event to notify all computed observables of a change in their dependencies and to schedule updates, which happens in depth-first order. The problem here occurs because bindings ignore the dirty
event and wait for a change
event, which will happen in a breadth-first order.
The fix has to happen in Knockout to make bindings respond to the dirty
events. This has already been checked in for the upcoming version (3.5.0): https://github.com/knockout/knockout/issues/2226
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With