2012-03-09 3 views
6

Я пытался понять это довольно давно. Я не мог найти ничего, что могло бы решить эту проблему, но, пожалуйста, поправьте меня, если я ошибаюсь.KnockoutJS: обновление/вставка данных в viewModel с использованием сопоставления

Проблема: У меня есть данные из API JSON, входящие в состав, с вложенной структурой массива/объекта. Я использую сопоставление, чтобы первоначально заполнить модель моими данными. Чтобы обновить это, я хочу расширить модель, если появятся новые данные, или обновить существующие данные.

Насколько я понял, ключ опции сопоставления должен делать этот трюк для меня, но я мог бы неправильно понять функциональность параметров сопоставления.

Я сводились эту проблему, чтобы быть представленными в этом примере:

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);​ 

Fiddle: http://jsfiddle.net/mikaelbr/gDjA7/

Как вы можете видеть, первая строка вставляет данные. Все хорошо. Но когда я пытаюсь обновить, он заменяет содержимое. То же самое для третьего отображения; он заменяет содержимое, а не расширяет его.

Я использую это неправильно? Должен ли я пытаться расширить содержимое «вручную» перед использованием сопоставления?

Редактировать Решение:
Я решил этот случай, имея второй вспомогательный массив, хранящий все существующие модели. По новым данным я расширил этот массив и обновил модель представления, чтобы содержать накопленные элементы.

При обновлении (в моем случае сообщение WebSocket) я прокрутил модели, изменил содержимое рассматриваемого элемента и использовал значение методаHasMutated(), чтобы уведомить измененное значение для библиотеки Knockout.

ответ

4

Глядя на вашем примере кода отображение плагин ведет себя точно так, как я бы ожидать, что она. Когда вы вызываете fromJS в коллекцию, вы эффективно сообщаете плагин сопоставления, это новое содержимое этой коллекции. Например:

На второй строке, как узнать, обновлялись ли вы или просто удалили идентификатор: 2?

Я не могу найти упоминания о подходящем методе, который обрабатывает данные как просто обновление, хотя вы можете добавить его. Массированные массивы поставляются с некоторыми полезными методами, такими как mappedIndexOf, чтобы помочь вам найти конкретные предметы. Если вы получаете набор данных обновления, просто пропустите его, найдите элемент и обновите его вызовом mapping.fromJS для этого конкретного элемента. Это можно легко обобщить на метод многократного использования. Метод

+0

Да. Это более или менее, как я решил это. – mikaelb

+0

Любые мысли по этому поводу: http://stackoverflow.com/questions/20397054/knockout-js-mapping-keys-and-kendo-ui-grid – jtromans

0

Да, вы должны сначала собрать все данные в список или массив, а затем применить сопоставление с этим списком. В противном случае вы будете перезаписывать значения в вашей модели viewModel.

1

Вы можете использовать ko.mapping.updateFromJS() для обновления существующих значений. Однако он не добавляет новые значения, поэтому это будет проблемой в вашем экземпляре. Взгляните на приведенную ниже ссылку для получения более подробной информации.

Using updateFromJS is replacing values when it should be adding them

+4

В updateFromJS() был удален в августе 2011 года https://github.com/SteveSanderson/knockout.mapping/commit/bff3c1864a5fd45289933b35de1ef70af4aed6b5 – mikaelb

+0

+1 @mikaelb - я не понял, что. Спасибо за информацию. –