【发布时间】:2017-12-16 08:07:10
【问题描述】:
我有一个 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));
});
}
我正在尝试将此调用的内容加载到一个名为“数据”的可观察对象中。之前已经声明过:
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()"
显示数据。但是,我在控制台中遇到错误:
Uncaught TypeError: Unable to process binding "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) 中的数据也不会更改。
【问题讨论】:
-
通过
Data.Description,您希望指向根视图模型中的Data属性或每个中的Data你的PlateTemplateGroups?换句话说,这个data-bind=...究竟在哪里(在什么范围内)?另外,你试过value: Data() && Data().Description && Data().Description()吗? -
你可以试试这个:ko.mapping.fromJS(data, {}, self.Data); (knockoutjs.com/documentation/plugins-mapping.html, '指定更新目标')。
-
谢谢@JoseLuis - 我都试过了。当我尝试这个时,我在尝试绑定我的视图的第一个字段上出现错误:无法处理绑定“值:函数(){return Data().Description()}”......当我删除(),编辑框为空。之前,它有来自 this.Data() 的数据。所以我不确定哪种方式是正确的以及为什么我没有得到任何数据。
-
@Craig 在这个 CodePen 中:codepen.io/anon/pen/KqJQqJ,如果你点击“加载数据”,数据就会更新。
ko.mapping.fromJS(parsed, {}, self.Data);工作正常。 -
等待等待等待!!!那行得通!你是一个美丽的人!哇...嗯,我得到了改进的结果。更改将返回到服务器!哇!我会修复它,因为它都被黑了,看看我是否完成了。谢谢。
标签: javascript c# asp.net-web-api knockout.js