2012-02-10 2 views
6

У меня возникают проблемы с обновлением пользовательского интерфейса, когда я получаю новые данные с сервера для одного элемента, который находится в наблюдаемом массиве объектов-оберток, который содержит объект нескольких наблюдаемых ,Не удается обновить пользовательский интерфейс нокаута с новым объектом данных

Рассмотрим следующий пример:

var vm = { 
.... 
localEdited: ko.mapping.fromJS(new ItemWrapper(defaultModelSerialised)), 
selected: ko.observable(null), 
editItem: function(data) { 
    // clone a temporary copy of data for the dialog when opening (*.localEdited on dialog) 
    var clonedData = ko.toJS(data); 
    ko.mapping.fromJS(clonedData, null, this.localEdited); 

    // selected should now point to the item in the obserable array which will be refreshed 
    this.selected(data); 

    // open dialog... 
}, 
submitDialog: function(data) { 

    // submit data to server... 

    // (1) commit the data back to UI (new item is return in resp.entity from server) 
    vm.selected(new ItemWrapper(resp.entity)); 

    // at this point the UI isn't showing the updated value 

    // (2) however if I do this it reflects the data change in the UI 
    this.selected().Name("changed"); // updates the UI. 
} 

Может кто-то объяснить, почему проходит в ItemWrapper в vm.selected не обновляет интерфейс, тогда как в (2) она работает. Я не хочу настраивать каждое свойство, как в (2) для каждого свойства.

ItemWrapper выглядит так:

function PoolWrapper(pool) { 
    this.Name = ko.observable(pool.Name); 

    // more properties... 
} 
+0

Вы связываете что-либо с vm.selected в html? Если нет, то почему вы ожидаете, что нокаут обновит интерфейс в этой строке vm.selected (новый ItemWrapper (resp.entity)); ? –

+0

Может быть, вы могли бы получить что-то в jsFiddle, чтобы продемонстрировать? Было бы легче видеть часть вашего кода. Я предполагаю, что, возможно, вы делаете 'с: selected' в своем пользовательском интерфейсе или используя шаблон против' selected'? –

+0

@RomanBataev: Ничто не связано с vm.selected напрямую. В файле editItem() данные передаются из ItemWrapper в наблюдаемом массиве. Затем выбранная переменная указывает на элемент в массиве. Как показывает точка (2), она привязана к UI ok при передаче свойств по отдельности, но не при передаче ItemWrapper в выбранную() переменную. – jaffa

ответ

6

OK- проблема в том, что ваши клоны в конечном итоге отображения мета-данные о них, и в конечном итоге это приводит к рекурсии при попытке вызова ko.mapping.fromJS.

Решение заключается в создании ваших клонов с использованием ko.mapping.toJS вместо ko.toJS, так что вы получите чистый клон (без метаданных отображения).

Вот обновленная скрипка: http://jsfiddle.net/rniemeyer/tDDBp/

+0

Спасибо за это. Не уверен, почему ko.toJS сохранит данные сопоставления, а ko.mapping.toJS - нет. – jaffa

+0

ko.mapping.toJS специально знает о параметрах сопоставления и удаляет их, а ko.toJS не имеет представления о плагине отображения. –

0

Что-то я наткнулся на сегодня, что я думал, что я разделю:

Если клон с помощью:

var clone = ko.mapping.fromJS(ko.mapping.toJS(itemToClone)); 

Затем клон будет лишенный любых вычисленных наблюдаемых. Они будут существовать в качестве последнего значения функции, но не будут функционировать в качестве вычисленного наблюдаемого.

Если деталь сложная модели с вычисленным наблюдаемыми, что вы хотели бы сохранить на свой клоне вы можете сделать следующее:

var clone = ko.mapping.fromJS(ko.mapping.toJS(itemToClone), null, new itemModel()); 

Где itemModel ваша комплексная модель для вашего пункта, содержащего ваш вычисленных наблюдаемыми.