KnockoutJS: обновление / вставка данных в viewModel с использованием сопоставления - PullRequest
6 голосов
/ 09 марта 2012

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

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

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

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

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

Скрипка: http://jsfiddle.net/mikaelbr/gDjA7/

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

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

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

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

Ответы [ 3 ]

4 голосов
/ 09 марта 2012

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

Во второй строке, Как он мог узнать, обновлялись ли вы или просто удалили id: 2?

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

1 голос
/ 09 марта 2012

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

Использование updateFromJS заменяет значения, когда они должны быть добавлены

0 голосов
/ 09 марта 2012

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

...