http://jsfiddle.net/toddhd/XWgK5/2/
看着小提琴手是看到这个的最好方法。如果您在具有开发者模式的浏览器(例如Chrome)或带有FireBug的FF中运行它并运行代码,您将在控制台中看到错误。它告诉我,我试图读取的值是未定义的。
错误发生在第50行:
if (item.Id == self.selectedOfferTypeDetailsType().Id) {
self.selectedOfferTypeDetailsType()。Id未定义
问题是,你会看到我在其他地方引用了这个相同的值,而且似乎在其他地方工作正常。显然我错过了一些东西......我的头靠在墙上两天了,可以用一双新鲜的眼睛。
答案 0 :(得分:2)
Damien和jaux都有敏锐的眼睛,但在这种情况下他们只是部分正确。确实,Knockout计算在声明后立即进行评估,因此Knockout可以确定您的计算需要订阅哪些其他可观察对象,但 。
计算后定义的初始评估正在运行而没有问题。但是,只要您调用ko.applyBindings,您的选择就会被连接起来并开始使用您的视图模型,那就是您的错误发生时。
一旦你的第一个选择(带有id = offerTypes)被绑定,它会做一些不寻常的事情:它会立即写入selectedOfferType 。这不是绑定选择通常工作的方式。通常,select会在用户更改内容之前不写入它的值,但在这种情况下,select绑定会立即将值写入SelectedOfferType。忍受我,我会告诉你我是如何发现错误的。
offerDetails正在观察SelectedOfferType,因此只要绑定了第一个select并将新值写入SelectedOfferType,offerDetails就会运行以检查它的值是否也已更改。在offerDetails中,您为selectedOfferTypeDetailsType写了一个值,该值警告其订阅者 - 订阅者包括“offer”。 “Offer”执行,但您只需将self.selectedOfferTypeDetailsType()设置为null(在offerDetails中),并且您无法读取“null”的“id”属性。
所以,问题是“为什么选择在绑定时将值写入SelectedOfferType?”答案在于你的绑定。初始化视图模型时,您似乎尝试使用offerTypes中的第二个值预设第一个下拉列表:
self.selectedOfferType = ko.observable(self.offerTypes()[1]);
和你的绑定
<select id="offerTypes" data-bind="options: offerTypes, ... value: selectedOfferType"></select>
同意您将值附加到您的选择中。但是,你将self.selectedOfferType设置为self.offerTypes()[1]中的对象,但是我在上面省略的绑定部分表示你的选项的值不是对象,而是等等值位于“Id”属性中。
<select data-bind="... optionsValue: 'Id', ..."></select>
将selectedOfferType与对象一起填充,但将optionsValue赋值给属性会导致Knockout理解selectedOfferType中的值无效(不可选),因此Knockout会立即使用第一个可能的选项值更新selectedOfferType。在这种情况下,为'0'。
触发一次写操作,触发所有订阅者,从而导致错误。
由于您编写的大多数代码都是为了期望selectOfferType中的对象,因此我只需从您的选择中删除“optionsValue:'Id'”。
对于冗长的回答,这是怎么回事? :-D
答案 1 :(得分:1)
在这种情况下,您需要做的是对计算属性进行评估。
创建viewModel实例时,self.selectedOfferTypeDetailsType将返回undefined。将deferEvaluation设置为true,计算出的商品的评估是延迟,直到您“消费”(确实需要)计算的商品。
self.offer = ko.computed({
read: function () {
var o = 'Not Found';
ko.utils.arrayForEach(self.offerTypeDetailsTypes(), function (item) {
if (item.Id == self.selectedOfferTypeDetailsType().Id) {
alert('Yay');
}
});
return o;
},
deferEvaluation : true
});
我希望这会有所帮助。
答案 2 :(得分:0)
问题在于:
self.offerDetails = ko.computed(function() {
var activeCategories = ko.observableArray();
ko.utils.arrayForEach(self.offerTypeDetailsTypes(), function (item) {
if (item.Id == self.selectedOfferType().Id)
activeCategories.push(item.DisplayName);
});
self.selectedOfferTypeDetailsType(activeCategories()[0]); // PROBLEM!
return activeCategories();
});
此时 self.selectedOfferTypeDetailsType
设置为字符串,毫无疑问,当您稍后尝试访问它时,它没有Id
属性。