我有一个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()
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)中的数据也不会更改。
答案 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();
});