将从服务器接收的对象转换为具有ko可观察属性的对象

时间:2016-01-11 14:45:27

标签: javascript knockout.js knockout-mapping-plugin

我遇到的问题似乎很简单。

我正在尝试从服务器提供的数据动态创建ko.observable()

服务器正在向我发送一个~240值的JSON数组。我希望为每个人创建一个可观察对象,因为我将它们放入在线表单中。

首先尝试

function AppViewModel() {

  var self = this;

  var data = {};

  $.getJSON("/record/20001", function(data) {
    $.each(data, function(i, val) {
      self.data[i] = ko.observable(val);
    });
  });


  self.test = 5;

  self.test2 = ko.observable(69);


}

vm = new AppViewModel();
ko.applyBindings(vm);

有了这个,我无法访问任何数据。

第二次尝试

function AppViewModel() {

    var self = this;
    self.abnorm_comment = ko.observable();
    self.abnorm_test1 = ko.observable();
    self.abo_sys_spec = ko.observable();
    self.access_location = ko.observable();
    self.ace_inhibit = ko.observable();

    /* 
    A myriad of line like these, written by hand
    */

    self.xray_other = ko.observable();


    $.getJSON("/record/20001", function (data) {
        $.each(data, function (i, val) {
            self[i](val);
        });
    });

    self.test = 5;

    self.test2 = ko.observable(69);


}

我想做什么

function AppViewModel() {

    var self = this;

    var data = {};


    $.getJSON("/record/20001", function (data) {
        $.each(data, function (i, val) {
            self.data[i] = ko.observable(val);
        });
    });

}

并按如下方式访问:

<input type="text" data-bind="value: data.case_id">

首次尝试时,我的视图模型中没有数据。如果我在Chrome控制台中提取vm变量,它确实拥有数据。

我在这里做错了吗?对于这么多可观察物,第二种方式看起来并不是很好。

如果我遗漏了一些明显的东西,请告诉我

个人解决方案

最终我在应用绑定和AJAX服务器请求之间遇到了竞争条件。我最终也使用了@JotaBe

推荐的插件

2 个答案:

答案 0 :(得分:2)

过去这对我来说是可靠的:

jsonToObservable = function (obj, data) {

    for (var p in data) {
        var temp = data[p];

        obj[p] = ko.observable(temp);

    }
};

答案 1 :(得分:1)

您可以使用ko.mapping插件来完成此操作。

优点是此插件经过了充分测试,能够映射更复杂的数据,如数组或嵌套属性。

您可以从JSON映射,也可以从已实例化的JavaScript对象映射。 synatx就像这样简单:

var viewModel = ko.mapping.fromJSON(data);

另一个优点是它还可以从来自服务器的新更新数据更新本地映射副本,而无需重建整个对象。这也有助于更新视图,而无需重建(或解除绑定)它。

最后一个优点是它还允许在需要将其发回服务器时返回JSON或JavaScript对象,就像这样:

var unmapped = ko.mapping.toJS(viewModel);