0

我有一个computed observableArray被调用者,它从另一个被调用者selectedToppings返回过滤后的数据。 应该返回所有属性设置为的浇头。在某些情况下,只能选择一种浇头,例如客户订购儿童大小的冰淇淋时。这是我的代码。observableArraytoppingsselectedToppingsobservableselectedtrue

<label>Multiple Toppings:
    <input type="checkbox" data-bind="checked: multiselectable" />
    <em data-bind="if: !multiselectable()">pick only one topping</em>
</label>
<h2>Available</h2>
<ul data-bind="foreach: toppings">
    <li data-bind="text: label, click: selected.bind($data, true)"></li>
</ul>
<h2>Selected</h2>
<ul data-bind="foreach: selectedToppings">
    <li data-bind="text: label, click: selected.bind($data, false)">
    </li>
</ul>
<script>
function Topping(options) {
    this.label = ko.observable(options.label);
    this.selected = ko.observable(false);
}
var iceCream = {
    toppings: ko.observableArray([
        new Topping({label: 'Sprinkles'}),
        new Topping({label: 'Marshmallows'}),
        new Topping({label: 'Nuts'})
    ]),
    multiselectable: ko.observable(false)
};
iceCream.selectedToppings = ko.computed(function () {
    return ko.utils.arrayFilter(iceCream.toppings(), function(item){
        return item.selected();
    });
});
var selectedSub = iceCream.selectedToppings.subscribe(function (toppings) {
    if (!this.multiselectable()) {
        if (toppings.length > 1) {
            var item = toppings.shift();
            item.selected(false);
        }
    }
}, iceCream);
ko.applyBindings(iceCream);
</script>

也在jsfiddle上。

availableToppings如果应该遵循它,我正在使用订阅来强制执行单顶规则。此实现不起作用,我不知道如何修复它。

什么不起作用:

  1. 确保未选中多选。
  2. 单击可用洒水。
  3. 单击可用的棉花糖。
  4. 单击可用的坚果。
  5. 单击可用洒水。
  6. 注意选择是如何没有改变的。
4

1 回答 1

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

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

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

功能顶部(选项){ 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);
于 2013-09-16T19:21:35.590 回答