Nueva instancia de modelo de vista de Durandal que aún refleja los valores anteriores

StackOverflow https://stackoverflow.com//questions/21012712

  •  21-12-2019
  •  | 
  •  

Pregunta

Me encontré con un problema extraño mientras probaba un escenario de composición ligeramente complejo usando durandal.

Quiero componer dinámicamente el contenido de cada celda de una tabla.Como ejemplo, tengo los siguientes archivos:

bienvenido.html => contiene el código para representar la tabla html dinámicamente

<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>

bienvenido.js => el modelo de vista correspondiente

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 => ver para mostrar la primera columna

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

cell-1.js => modelo de vista correspondiente para la celda-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;
});

Y de manera similar, una vista y un modelo de vista para la celda-2.

El problema al que me enfrento es que aunque la composición funciona bien y la función de activación se llama dos veces para cell-1.js (una vez por cada fila), el valor del observable name contendría el valor anterior. (es decir,el valor sería "John" cuando intente establecerlo en "Morgan").Esto es extraño ya que cell-1.js devuelve un constructor y, por lo tanto, durandal debería haber creado otra instancia del modelo de vista.En resumen, esto da como resultado que ambas filas contengan los mismos datos.

Estoy seguro de que hay algo menor que tengo que modificar para que funcione, pero todo mi esfuerzo ha sido en vano.

Cualquier ayuda sería muy apreciada.

¿Fue útil?

Solución

El problema es que has declarado tu model y name variables en el nivel del módulo en su cell-1.js.

Entonces, incluso si devuelve un constructor al que se llama dos veces, el módulo en sí solo se carga una vez, por lo que sus modelos de vista comparten el mismo estado.

Para resolverlo solo necesitas mover tus variables dentro del 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;
});
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top