Новый экземпляр durandal viewmodel по-прежнему отражает предыдущие значения

Я столкнулся со странной проблемой, пытаясь создать несколько сложный сценарий композиции с использованием Durandal.

Я хочу динамически составлять содержимое каждой ячейки таблицы. В качестве примера у меня есть следующие файлы:

welcome.html => содержит код для динамического отображения html-таблицы.

<table>
    <thead>
        <tr data-bind="foreach: columnNames">
            <th><span data-bind="text: $data"></span>

            </th>
        </tr>
    </thead>
    <tbody data-bind="foreach: items">
        <tr data-bind="foreach: $parent.columnNames">
            <!-- <td data-bind="text: $parent[$data]"></td>-->
            <td data-bind="compose: { model: $root.activeView($index), activationData: $root.activationData($parentContext.$index), cacheViews: false }"></td>
        </tr>
    </tbody>
</table>

welcome.js => соответствующая модель представления

define(['knockout'], function (ko) {
var ctor = function () {
    var m_items = [{
        'Name': 'John',
        'Age': 25
    }, {
        'Name': 'Morgan',
        'Age': 26
    }];
    this.items = ko.observableArray(m_items);
    this.columnNames = ko.computed(function () {
        if (m_items.length === 0)
            return [];
        var props = [];
        var obj = m_items[0];
        for (var name in obj)
            props.push(name);
        return props;
    });

    this.activeView = function (index) {
        if (index() == 0)
            return "viewmodels/cell-1";
        else
            return "viewmodels/cell-2";
    };

    this.activationData = function (rowIndex) {
        return m_items[rowIndex()];
    }

};

return ctor;
});

cell-1.html => представление для отображения в первом столбце

<span data-bind="text : Name"></span>

cell-1.js => соответствующая модель представления для ячейки-1

define(['knockout'], function (ko) {
var model = null;
var name = ko.observable();
var ctr = function () {
    this.Name = name;
    this.activate = function (modelObject) {
        model = modelObject;
        name(model.Name);
    };
};
return ctr;
});

А так же вид и модель вида для ячейки-2.

Проблема, с которой я сталкиваюсь, заключается в том, что, хотя композиция работает нормально, а функция активации вызывается дважды для ячейки-1.js (один раз для каждой строки), значение наблюдаемого name будет содержать предыдущее значение (т. е. значение будет «Джон», когда он пытается установить его на «Морган»). Это странно, так как cell-1.js возвращает конструктор и, следовательно, Durandal должен был создать еще один экземпляр модели представления. Подводя итог, это приводит к тому, что обе строки содержат одни и те же данные.

Я уверен, что есть что-то незначительное, что мне нужно настроить, чтобы заставить его работать, но все мои усилия были напрасны.

Любая помощь будет принята с благодарностью.


person user3120027    schedule 09.01.2014    source источник


Ответы (1)


Проблема в том, что вы объявили свои переменные model и name на уровне модуля в файле cell-1.js.

Таким образом, даже если вы возвращаете конструктор, который вызывается дважды, сам модуль загружается только один раз, поэтому ваши модели просмотра используют одно и то же состояние.

Чтобы решить эту проблему, вам просто нужно переместить переменные внутри ctr:

define(['knockout'], function (ko) {

var ctr = function () {
    var model = null;
    var name = ko.observable();

    this.Name = name;
    this.activate = function (modelObject) {
        model = modelObject;
        name(model.Name);
    };
};
return ctr;
});
person nemesv    schedule 09.01.2014
comment
Отлично.. Спасибо, что поймали это! - person user3120027; 09.01.2014