Knockout.js - 如何设置用作参考的observable?

时间:2014-05-28 18:47:32

标签: javascript knockout.js

我正在设置一个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)无效。

希望有人可以帮助我!谢谢!

3 个答案:

答案 0 :(得分:0)

在我看来,你做得恰到好处:

oo.PlanId = data.PlanId;

在您自己的Model中创建对私有data.observable的引用。在" CustomizePlan"你可以设置oo.PlanId或data.PlanId来改变它们的值。

也许你在为Stack Overflow上的帖子创建示例代码时克服了这个问题?看看这个小提琴,这对我有用:

http://jsfiddle.net/FMGd6/1/

好的,所以我也会指出另一件事:当您使用值绑定绑定到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