Wait with executing ko.computed until applyBindings

889 views Asked by At

Say you have a view model with a circular dependency. I know you should avoid this in normal circumstances, but for this case assume you can't because it's out your control. A parent and a child refer to each other. Below is for brevity a very simplified example:

Html:

<div id="root">
    <div data-bind="text: parent.childName()"></div>
</div>

JS:

var page = {};

page.parent = 
{ 
    name: ko.observable('parent'), 
    childName: ko.computed(function() { return page.child.name(); })
};
page.child = 
{ 
    name: ko.observable('child'), 
    parentName: ko.computed(function() { return page.parent.name(); })
};

ko.applyBindings(page, document.getElementById('root') );

JS Fiddle

The problem is that ko.computed is executed the first time it is initialized. If it would only execute at the moment of applyBindings everything would be perfectly fine.

One solution would be to remove ko.computed altogether and just use a plain normal function. Those are only executed at the moment of applyBindings. Problem is of course that you lose all the other advantages of ko.computed, like losing the caching functionality etc.

Is there a way to say that a computed observable only starts initializing at the applyBindings phase?

2

There are 2 answers

0
manji On

Use deferEvaluation option to postpone the computed evaluation to when it's first accessed:

ko.computed({
    read: function() { return page.parent.name(); },
    deferEvaluation: true
});

JSFiddle

2
lante On

Another solution:

childName: ko.computed(function() { return page.child && page.child.name(); }).

It will return undefined if child not set;