强制Knockout计算observableArray的长度为1(一)

时间:2013-09-16 18:27:55

标签: knockout.js knockout-mvc knockout-mvvm knockout-subscribe

我有一个名为computed的{​​{1}} observableArray,它会从另一个名为selectedToppings的{​​{1}}返回过滤后的数据。 observableArray应该返回toppings属性selectedToppings设置为observable的所有配件。在某些情况下,只能选择一种浇头,例如,如果顾客订购儿童大小的冰淇淋。这是我的代码。

selected

同样在jsfiddle

我正在使用true上的订阅来强制执行一流的规则(如果应该遵循该规则)。这个实现不起作用,我不知道如何解决它。

什么不起作用:

  1. 确保未选中多重选择。
  2. 点击Available Sprinkles。
  3. 点击Available Marshmallows。
  4. 点击Available Nuts。
  5. 点击Available Sprinkles。
  6. 注意选择如何不变。

1 个答案:

答案 0 :(得分:1)

已经发生变化后,通常很难管理数据违规行为。在您的示例中,防止用户首先进行无效选择更容易,更可靠,而不是在检测到错误输入后尝试“修复”。业务规则应该在流程的后期应用,以验证多重选择是否得到遵守,如果不是,则抛出警告或异常,但用户界面可以在这些错误发生之前防止大部分错误。

以下是使用您显示的代码阻止无效选择的一种方法:查看小提琴

这是可用配件的视图:

<h2>Available</h2>
<ul data-bind="foreach: toppings">
    <li data-bind="text: label, click: selected.bind($data, ($parent.multiselectable() || $parent.selectedToppings().length === 0) && true)"></li>
</ul>

考虑到这一点,我会考虑采用略有不同的方法

看看这个:JS Fiddle

考虑从冰淇淋本身中分离出可用的配料清单。这将允许您扩展您的示例以包含许多冰淇淋实例,而不需要每个实例都需要维护所有可能的浇头列表以及是否每个浇头都被选中。

相反,考虑一个浇头列表,让每个冰淇淋对象实例包含一个仅添加到该冰淇淋实例的浇头的数组。

function Topping(options){         this.label = ko.observable(options.label);     }

function IceCream(){
    this.toppings = ko.observableArray([]);
};

var toppings = ko.observableArray([
        new Topping({label: 'Sprinkles'}),
        new Topping({label: 'Marshmallows'}),
        new Topping({label: 'Nuts'})
    ]);
var iceCream = new IceCream();
var multiselectable = ko.observable(false);
var viewModel = {
    multiselectable: multiselectable,
    iceCream: iceCream,
    toppings: toppings,
    addTopping: function(topping){
        if( multiselectable() || iceCream.toppings().length < 1)
            if( iceCream.toppings.indexOf(topping) == -1 )
                iceCream.toppings.push(topping);
    },
    removeTopping: function(topping){
        iceCream.toppings.remove(topping);
    }
};

ko.applyBindings(viewModel);