2012-03-09 6 views
6

He estado tratando de resolver esto desde hace bastante tiempo. No pude encontrar nada que solucione este problema, pero por favor corrígeme si me equivoco.KnockoutJS: Actualizar/Insertar datos en un modelo de vista usando mapeo

Problema: Tengo datos de una API JSON entrando, con una matriz anidada/estructura de objetos. Uso el mapeo para llenar inicialmente el modelo con mis datos. Para actualizar esto, quiero extender el modelo si llegan nuevos datos o actualizar los datos existentes.

Por lo que descubrí, la clave de opción de mapeo, debería hacer este truco para mí, pero podría haber malinterpretado la funcionalidad de las opciones de mapeo.

He reducía el problema a ser representado por el siguiente ejemplo:

var userMapping = { 
    key: function(item) { 
     return ko.utils.unwrapObservable(item.id); 
    } 
}; 

// JSON call replaced with values 
var viewModel = { 
    users: ko.mapping.fromJS([], userMapping) 
}; 

// Should insert new - new ID? 
ko.mapping.fromJS([{"id":1,"name":"Foo"}, {"id":2,"name":"Bar"}], userMapping, viewModel.users); 

// Should only update ID#1 - same ID? 
ko.mapping.fromJS([{"id":1,"name":"Bat"}], userMapping, viewModel.users); 

// Should insert new - New ID? 
ko.mapping.fromJS([{"id":3,"name":"New"}, {"id":4,"name":"New"}], userMapping, viewModel.users); 

ko.applyBindings(viewModel);​ 

violín: http://jsfiddle.net/mikaelbr/gDjA7/

Como se puede ver, la primera línea inserta los datos. Todo bien. Pero cuando intento actualizar, reemplaza el contenido. Lo mismo para el tercer mapeo; reemplaza el contenido, en lugar de ampliarlo.

¿Lo estoy usando mal? ¿Debo tratar de extender el contenido "manualmente" antes de usar el mapeo?

Editar Solución:
que resuelve este caso por tener una segunda matriz ayudante de almacenar todos los modelos actuales. En los datos nuevos amplié esta matriz y actualicé el modelo de vista para contener los elementos acumulados.

En la actualización (En mi caso, un mensaje de WebSocket), hice un bucle a través de los modelos, cambié el contenido del artículo en cuestión, y usé el método valueHasMutated() para notificar el cambio de valor a la lib de Knockout.

Respuesta

4

De mirar el código de ejemplo el plugin de mapeo se comporta exactamente lo que cabe esperar que lo haga. Cuando llamas al fromJS en una colección, efectivamente le estás diciendo al plugin de mapeo que este es el contenido nuevo de esa colección. Por ejemplo:

En la segunda línea, ¿cómo podría saber si estaba actualizando o si simplemente había eliminado id: 2?

No puedo encontrar ninguna mención de un método adecuado que trate los datos simplemente como una actualización, aunque podría agregar uno. Las matrices asignadas vienen con algunos métodos útiles, como mappedIndexOf, para ayudarlo a encontrar artículos en particular. Si recibe un conjunto de datos de actualización, simplemente recorra, busque el elemento y actualícelo con una asignación desde la llamada JS a ese elemento en particular. Esto puede generalizarse fácilmente en un método reutilizable. Método

+0

Sí. Esto es más o menos cómo lo resolví. – mikaelb

+0

Cualquier idea sobre esto: http://stackoverflow.com/questions/20397054/knockout-js-mapping-keys-and-kendo-ui-grid – jtromans

0

Sí, primero debe recopilar todos los datos en una lista o matriz y luego aplicar la asignación a esa lista. De lo contrario, va a sobrescribir los valores en su viewModel.

1

Puede usar ko.mapping.updateFromJS() para actualizar los valores existentes. Sin embargo, no agrega nuevos valores, por lo que sería un problema en su instancia. Eche un vistazo al siguiente enlace para más detalles.

Using updateFromJS is replacing values when it should be adding them

+4

Los updateFromJS() se retiró en agosto de 2011. https://github.com/SteveSanderson/knockout.mapping/commit/bff3c1864a5fd45289933b35de1ef70af4aed6b5 – mikaelb

+0

1 @mikaelb - No me daba cuenta de eso. Gracias por la info. –

Cuestiones relacionadas