我正在设置一个observable,但它总是返回“undefined”。 解释起来并不容易,所以我将展示我正在尝试做的事情。
检查底部的更新 - 它包含一个可以重现问题的小提琴(jsfiddle.net/4uRj5/9)。
结构
我有一个主视图模型,结构如下:
function PurchasePlanViewModel() {
var main = this;
// Global Data
var data = new function () {
var data = this;
data.PlanId = ko.observable();
data.Monitors = ko.observable();
data.Commands = ko.observable();
data.HistoryDays = ko.observable();
// ...
};
// SubViewModels
main.SubscriptionForm = new function () {
var o = this;
o.SelectPlan = new function () {
var oo = this;
// Data
oo.PlanId = data.PlanId;
// ...
// Methods
oo.ChoosePlan = function (selectedplan) { // do something ... };
oo.CustomizePlan = function () {
// do something ...
data.PlanId(0);
};
// ...
};
};
};
名为“data”的结构表示页面处理的所有数据,我将其定义为全局私有对象,因此不能直接在HTML绑定中使用,而是用作子视图模型的引用。
每个数据只能通过相应的子视图模型进行绑定,因此,每个子视图模型都需要在本地定义引用全局数据的数据。
一切正常,绑定工作得很好,所有对象都是同步的,甚至是不同子视图模型共有的对象。
问题
正如我所说,一切正常,直到我需要在用户选择自定义计划时手动将PlanId设置为0。
在oo.CustomizePlan中,我将data.PlanId设置为0 ......但它不起作用。当我尝试获取data.PlanId值时,它返回undefined。
我做了一些测试,我发现oo.PlanId = data.PlanId是造成这种不良行为的原因。
问题
如何在此结构中设置data.PlanId? 我缺少什么?
我真的想保留这个结构(仅限私有数据的结构)。
更新 我使用上面的代码创建了FIDDLE。 单击“创建自定义计划”时,data.PlanId(0)无效。
希望有人可以帮助我!谢谢!
答案 0 :(得分:0)
在我看来,你做得恰到好处:
oo.PlanId = data.PlanId;
在您自己的Model中创建对私有data.observable的引用。在" CustomizePlan"你可以设置oo.PlanId或data.PlanId来改变它们的值。
也许你在为Stack Overflow上的帖子创建示例代码时克服了这个问题?看看这个小提琴,这对我有用:
好的,所以我也会指出另一件事:当您使用值绑定绑定到select时,您的observable会对select选项中的值进行约束。作为淘汰文件中的州议员:
但是如果将模型值设置为列表中没有相应条目的内容会发生什么?默认行为是Knockout覆盖您的模型值以将其重置为下拉列表中已选择的任何内容,从而防止模型和UI失去同步。
http://knockoutjs.com/documentation/value-binding.html
您只能设置" 1"," 2"和" 3" (注意:这些与1,2,3不同,因为它们是整数)
答案 1 :(得分:0)
我认为这里的问题是孤立的范围。我能够解决问题,你可以在JSFiddle中找到它。
我试图保留您的数据结构,但我认为我们不需要在子视图模型中复制数据属性。在您的示例中,数据只有一个属性(PlanId)。在这种情况下,我没有看到复制它的主要问题。但随着数据属性的增加,在子模型中复制它们所涉及的复杂性也会增长。
因此,我将子模型数据设置为全局数据的可观察数据,一切正常。而且,在我的观察中,这是有道理的。
您的viewmodel将如下所示:
main.SubscriptionForm = new function () {
var o = this;
o.SelectPlan = new function () {
var oo = this;
// Data is an observable
oo.data = ko.observable(data);
// ...
// Methods
oo.CustomizePlan = function () {
// do something ...
alert(oo.data().PlanId());
oo.data().PlanId(0);
alert(oo.data().PlanId());
};
// ...
};
};
您的模板如下所示:
<div data-bind="with: SelectPlan">
<select data-bind="value: data().PlanId">
<option value="0">Choose a Plan...</option>
<option value="1">Plano 01</option>
<option value="2">Plano 02</option>
<option value="3">Plano 03</option>
</select>
<button data-bind="click: CustomizePlan">Create a Custom Plan</button>
</div>
答案 2 :(得分:0)
实际上,我发现了确切的问题。您的默认选项是String。
<option>Choose a Plan...</option>
在下一个选项中,您将它们视为整数
<option value="1">Plano 01</option>
并将它们更新为整数...
data.PlanId(0);
修复1:
将默认值更新为0
<option value="0">Choose a Plan...</option>
修复2:
手动更新PlanId时,请将它们作为常规字符串处理。
data.PlanId("1");
我创建了另一个JSFiddle来解决修复1 。