从服务器更新时,集合对象的计算属性不会更新

时间:2018-05-09 12:45:04

标签: knockout.js

我有一个视图模型(Form),上面有一个集合(Reasons)。我希望能够彼此独立地保存这些原因。

我在javascript对象上有一个计算属性(NeedsSaving)。我使用此属性让集合中每个项目的UI在保存按钮或完整按钮之间翻转。

在初始页面加载时工作正常,但是一旦我对文本进行了更改,然后单击Save,从服务器重新加载项目,NeedsSaving属性不会更新并说它仍然处于已更改状态,并且保存按钮将在它应该翻转回完整按钮时保持显示。

原因形式:

var reasonForm = function(data, parent) {
  let self = this;
  self.parent = parent;

  ko.mapping.fromJS(data, reasonFormMapping, self);

  self.Reasons = ko.observableArray();

  self.saveReason = function (reason) {
    .ajax({
    // omitted
    }).done(function (response) {
      ko.mapping.fromJS(response.data, {}, reason);
    })
    // omitted

  };
}

原因:

var reason = function(data) {
  let self = this;
  let originalReason = data.Reason;

  self.Reason = ko.observable();
  self.IsComplete = ko.observable(false);
  self.NeedsSaving = ko.computed(function() {
    return self.Reason() != originalReason;
  });

  ko.mapping.fromJS(data, {}, self);
}

来自服务器的响应示例

{
  "success":true,
  "message":"Reason #4 changes saved.",
  "data": {
    "Number":4,
    "Reason":"asdfasdfasdf",
    "IsComplete":false
  }
}

第一次单击“保存”时,它会正确地将数据保存到数据库,但在第一次单击后它不再起作用。我不确定我的映射是否错误或我做错了什么。

修改 所以我将ajax调用的.done函数更改为以下内容:

var model = new reason(response.data);
ko.mapping.fromJS(model, {}, reason);

第一行是好的,所有属性仍然是可观察的。但在使用第二行映射后,NeedsSaving属性已更改为常规布尔属性而非可观察属性。这导致UI出错,但为什么这样做呢?

1 个答案:

答案 0 :(得分:1)

我认为问题是你只设置originalReason一次,所以在第一次保存之后你的计算将总是返回true。

快速解决方法是在originalReason个对象上提供reason,然后在响应处理程序中手动设置originalReason

这是一个缩减codepen

解决此类问题的更好方法是(imo)实现像this example

这样的脏标志