无法使用新数据对象更新Knockout UI

时间:2012-02-10 10:29:48

标签: javascript knockout.js

当我从服务器获取单个项目的新数据时,我正在遇到UI刷新问题,该项目位于包含多个可观察对象的包装对象的observableArray中。

请考虑以下事项:

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不会更新UI,而在(2)中它可以工作。我不想为每个属性设置像(2)中的每个属性。

ItemWrapper看起来像这样:

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

    // more properties...
} 

2 个答案:

答案 0 :(得分:6)

好的 - 问题是你的克隆最终会在它们上映射元数据,最终在尝试调用ko.mapping.fromJS时会导致递归。

解决方案是使用ko.mapping.toJS而不是ko.toJS来创建克隆,以便获得干净的克隆(无需映射元数据)。

这是一个更新的小提琴:http://jsfiddle.net/rniemeyer/tDDBp/

答案 1 :(得分:0)

我今天偶然发现了一些我认为我会分享的内容:

如果使用以下方法克隆:

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

然后克隆将删除任何计算的可观察量。它们将作为函数的最后一个值存在,但不再作为计算的可观察对象。

如果您的项目是具有计算可观察量的复杂模型,您希望保留在克隆上,则可以执行以下操作:

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

其中itemModel是包含计算的observable的项目的复杂模型。