无法查看oservable上的数据

时间:2017-07-12 04:30:15

标签: javascript c# asp.net-web-api knockout.js

我有一个View模型,它有一个loaddata函数。它没有构造函数。如果ID字段有值,我希望它调用loadData方法。

该字段是通过以下方式获得的:

self.TemplateId = ko.observable($("#InputTemplateId").val());

然后,在我的ViewModel的末尾,我有一些代码检查它,并调用我的加载函数:

if (!self.CreateMode()) {
        self.loadData();
    }

我的load方法调用我的.Net WebAPI方法,该方法返回一个非常复杂的结构。该结构是一个类,包含几个字段和一个数组/列表。该列表中的项目是一些基本字段,另一个是列表/数组。然后那个对象只有几个字段。所以,这是3个级别。具有对象列表的对象和这些对象各自具有另一个对象列表......

我的WebAPI通话正在运行。我调试了它,数据完全恢复了。

self.loadData = function () {
        $.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) {
            self.Data(ko.mapping.fromJS(data));

        });
    }

我正在尝试将此调用的内容加载到名为“Data”的可观察对象中。它早先宣布:

self.Data = ko.observable();

要加载它,并保持一切可观察,我正在使用Knockout映射插件。

self.Data(ko.mapping.fromJS(data));

当我断断续续的时候,我看到了我对这两个数据的期望(API调用的结果)和self.Data()

enter image description here

self.Data似乎是我加载的数据的可观察版本。所有数据都在那里,一切似乎都是正确的。

我能够提醒数据对象根目录中某个字段的值:

alert(self.Data().Description());

我还能够在列表的第一项中看到一个字段。

alert(self.Data().PlateTemplateGroups()[0].Description());

这向我表明Data是一个可观察的并包含数据。我想我以后可以将self.Data发布回我的API来保存/更新。

现在,问题开始了。

在我的视图中,我试图显示一个驻留在我的复杂项目的根类中的字段。我上面提醒过的东西。

<input class="form-control" type="text" placeholder="Template Name" data-bind="value: Data.Description">

我没有错误。然而,文本框是空的。

如果我将输入框的代码更改为:

data-bind="value: Data().Description()"

显示数据。但是,我在控制台中遇到错误:

  

未捕获的TypeError:无法处理绑定“value:function   (){return Data()。Description()}“消息:无法读取属性   '描述'未定义

我认为这是由于视图加载,在从WebAPI调用加载数据之前,因此,因为我使用ko.mapping - 视图不知道什么是Data()。Description()是...它就死了。

有没有办法解决这个问题,以便我能够实现我想做的事情?下面是完整的ViewModel。

function PlateTemplateViewModel() {
    var self = this;

    self.TemplateId = ko.observable($("#InputTemplateId").val());
    self.CreateMode = ko.observable(!!self.TemplateId() == false);

    self.IsComponentEditMode = ko.observable(false);
    self.IsDisplayMode = ko.observable(true);
    self.CurrentComponent = ko.observable();

    self.Data = ko.observable();

    self.EditComponent = function (data) {

        self.IsComponentEditMode(true);
        self.IsDisplayMode(false);
        self.CurrentComponent(data);

    }
    self.loadData = function () {
        $.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) {
            self.Data(ko.mapping.fromJS(data));

        });
    }

    self.cancel = function () {
        window.location.href = "/PlateTemplate/";
    };

    self.save = function () {
        var data = ko.mapping.toJS(self.Data);
        $.post("/api/PlateTemplate/Save", data).done(function (result) {
            alert(result);
        });
    };

    if (!self.CreateMode()) {
        self.loadData();
    }
}

$(document).ready(function () {
    ko.applyBindings(new PlateTemplateViewModel(), $("#plateTemplate")[0]);
});

也许答案是在ready()函数中进行加载,并将数据作为参数传递?不知道当我想创建一个新项目时会发生什么,但我可以做到。

此外,当我尝试保存时,我注意到即使我可能更改视图中的字段(例如,更新描述),观察视图模型(self.Data)中的数据也不会更改。

1 个答案:

答案 0 :(得分:1)

您的输入字段可能是:

<div data-bind="with: Data">
    <input class="form-control" type="text" placeholder="Template Name" data-bind="value: Description">
 </div>

我更喜欢使用with作为清洁工,并且应该避免您遇到的混乱和问题。

错误的原因是因为在加载数据之前已经绑定了html。因此,要么在加载数据之前不应用绑定:

$.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) {
        self.Data(ko.mapping.fromJS(data));
        ko.applyBindings(self, document.getElementById("container"));
    });

或者用if包装模板,因此它不会给你这个错误,因为数据最初是未定义的。

self.Data = ko.observable(); // undefined

<!-- ko if: Data -->
<div data-bind="with: Data">
    <input class="form-control" type="text" placeholder="Template Name" data-bind="value: Description">
 </div>
<!-- /ko -->

此外,如果您知道数据模型将是什么,您可以将数据默认为此。

self.Data = ko.observable(new Data());

应用绑定方法:

var viewModel = null;
$(document).ready(function () {
    viewModel = new PlateTemplateViewModel();
    viewModel.loadData();
});