I have a computed observableArray called selectedToppings which returns filtered data from another observableArray called toppings. selectedToppings should return all toppings that have their observable property of selected set to true. In some situations, only one topping can be selected, such as if a customer is ordering the child-sized ice cream. Here is my code.
<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>
Also on jsfiddle.
I am using a subscription on availableToppings to enforce the one-topping rule if it is supposed to be followed. This implementation is not working, and I am not sure how to fix it.
What is not working:
- Ensure multiselectable is not checked.
- Click on Available Sprinkles.
- Click on Available Marshmallows.
- Click on Available Nuts.
- Click on Available Sprinkles.
- Notice how the selection does not change.