[英]KnockoutJS Binding Issue - Cannot read property
我有一个简单的Knockout问题,但我是一个完全的初学者。 我扔了这个代码页,其他人已经工作但从未完成。
首次加载此页面时,将检索数据并正确加载主网格。 当我尝试自动选择结果中的第一条记录以便在网格下方填写详细列表时,会出现问题。
当发生这种情况时,我收到以下消息。
未捕获的TypeError:无法处理绑定“text:function(){return selected.RequestLog.Timestamp}”,消息:无法读取未定义的属性“Timestamp”
这是我正在使用的代码片段。 返回的数据来自实体框架。
var siteLogModel = function () {
var self = this;
self.errorList = ko.observableArray([]);
self.selected = ko.observable();
self.updateErrorList = function (page) {
jQuery.ajax({
type: "POST",
url: "/Admin/ErrorPage",
data: { pageNum: page },
success: function (result) {
self.errorList(result);
self.selected(result[0]);
// Since we have success, add the click handler so we can get the details about a row by id.
//addRowHandlers();
},
error: function (result) {
jQuery("#status").text = result;
}
});
};
};
这是在加载数据后尝试发生的实际绑定。 RequestLog似乎并不在结合时存在,即使它似乎是确定的,如果我在上面的函数中设置断点上self.selected线(结果[0])。
我认为这是一个范围问题,但我不能为我的生活考虑如何最好地解决它。 任何帮助,将不胜感激。
<div class="param">
<span>Time</span>
<label data-bind="text: selected.RequestLog.Timestamp"></label>
</div>
更新:这是文档就绪部分。
jQuery(document).ready(function () {
var vm = new siteLogModel();
vm.updateErrorList(0);
ko.applyBindings(vm);
});
在ko评估绑定表达式时,您selected
observable没有.RequestLog
属性。 该错误来自javascript,而不是ko(虽然ko在您看到的错误消息中包含异常)。 运行时, selected.RequestLog === undefined
为true,你不能在undefined上调用任何东西。 它就像一个空引用异常。
如果在ajax调用完成之前调用applyBindings
,则有意义。
通过执行计算来解决此问题的一种方法:
<div class="param">
<span>Time</span>
<label data-bind="text: selectedRequestLogTimestamp"></label>
</div>
self.selectedRequestLogTimestamp = ko.computed(function() {
var selected = self.selected();
return selected && selected.RequestLog
? selected.RequestLog.TimeStamp
: 'Still waiting on data...';
});
有了上述内容,在未定义的变量上不会调用任何内容。 在ajax调用完成之前,您的标签将显示“仍在等待数据”,然后只要您调用self.selected(result[0])
,它就会填充时间戳。
解决它的另一种方法是保持绑定相同,但通过给选定的observable一个初始值。 您可以将所有html保留为原样,只是为此:
self.selected = ko.observable({
RequestLog: {
TimeStamp: 'Still waiting on data'
}
});
......最终会得到相同的结果。
为什么?
通过执行self.prop = ko.observable()
类的self.prop = ko.observable()
初始化observable时,observable的实际值是undefined
。 试试看:
self.prop1 = ko.observable();
var prop1Value = self.prop1();
if (typeof prop1Value === 'undefined') alert('It is undefined');
else alert('this alert will not pop up unless you initialize the observable');
总结一下发生了什么:
text: selected.RequestLog.Timestamp
绑定。 所有这些都发生在你的ajax调用返回之前。
回复评论#1
是的,您可以在ajax成功事件后调用applyBindings。 但是,这通常并不总是你应该做的。 如果你愿意,这里有一个如何做到的例子:
self.updateErrorList = function (page) {
self.updateErrorPromise = jQuery.ajax({
type: "POST",
url: "/Admin/ErrorPage",
data: { pageNum: page },
success: function (result) {
self.errorList(result);
self.selected(result[0]);
},
error: function (result) {
jQuery("#status").text = result;
}
});
};
jQuery(document).ready(function () {
var vm = new siteLogModel();
vm.updateErrorList(0);
vm.updateErrorPromise.done(function() {
ko.applyBindings(vm);
});
});
另一种方法是继续eager-bind(在ajax调用完成之前applyBindings),但是将你的标记包装在if绑定中,如下所示:
<div class="param" data-bind="if: selected">
<span>Time</span>
<label data-bind="text: selected.RequestLog.Timestamp"></label>
</div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.