Search code examples
knockout.jsdurandalknockout-2.0durandal-navigation

Dynamic composition using knockout and durandal doesn't work


I have a strange problem while using Durandal/Knockout. In some cases the binding doesn't work properly. I've simplified my situation which came in this question.

I'm setting composition info somewhere in my code like:

compositionInfo({
    model: viewModelInstance,
    view: viewName,
    activate: viewModelInstance.activate
    });

And this is my view:

<div id="service-container" 
    data-bind="compose: { model: compositionInfo().model,
                          view: compositionInfo().view, 
                          activate: compositionInfo().activate}">

At the first time, the composition works fine. But on the next time when the compositionInfo changes (using the same lines and in the same place of the code), nothing happens.

The first time there is a ["Activating",...] in the log window. But in the second time there's no such log or ["Binding"] log.

I've traced the Durandal and Knockout code and find out that in the knockout-2.3.0.debug file there's a evaluateImmediate() function which runs this line on first time (correct ones):

var newValue = readFunction.call(evaluatorFunctionTarget);

and causes the composition to start to activating the model.

But when it's not working in the evaulateImmediate() it returns some lines above by this code:

// Don't dispose on first evaluation, because the "disposeWhen" callback might
// e.g., dispose when the associated DOM element isn't in the doc, and it's not
// going to be in the doc until *after* the first evaluation
if (_hasBeenEvaluated && disposeWhen()) {
    dispose();
    return;
}

What is this code for? Everything works fine if I comment these lines.

This problem varies computer to computer. On my computer in most cases it just work the first time. but on other computer it works most of the time and fails about 3/10 cases.

FYI I'm using Durandal 1.1.1 and Knockout 2.3.0


Solution

  • As I mentioned in the question, using durandal 1.2 the only way to have proper binding is to commend these lines:

    // Don't dispose on first evaluation, because the "disposeWhen" callback might
    // e.g., dispose when the associated DOM element isn't in the doc, and it's not
    // going to be in the doc until *after* the first evaluation
    if (_hasBeenEvaluated && disposeWhen()) {
        dispose();
        return;
    }
    

    But after upgrading to Durandal 2.0.1, these commented lines causes some activations to happen more than once.

    So keep in mind if you upgrade to 2.0.1 uncomment these lines or just get the original knockout code.