KnockoutJS ObservableArray data grouping
http://stackoverflow.com/questions/9877301/knockoutjs-observablearray-data-grouping
by Doug Hill
HTML
<script src="http://knockoutjs.com/downloads/knockout-2.0.0.debug.js"></script>
<ul data-bind="foreach: people">
<li>
<input data-bind="value: name" />
<select data-bind="options: $root.choices, value: type"></select>
<a href="#" data-bind="click: $root.removePerson"> x </a>
</li>
</ul>
<button data-bind="click: addPerson">Add Person</button>
<hr/>
<ul data-bind="foreach: choices">
<li>
<h2 data-bind="text: $data"></h2>
<ul data-bind="foreach: $root.people.index.type()[$data]">
<li data-bind="text: name"></li>
</ul>
<hr/>
</li>
</ul>
CSS
h2 { font-size: 1.2em; font-weight: bold; }
JavaScript
ko.observableArray.fn.distinct = function(prop) {
var target = this;
target.index = {};
target.index[prop] = ko.observable({});
ko.computed(function() {
//rebuild index
var propIndex = {};
ko.utils.arrayForEach(target(), function(item) {
var key = ko.utils.unwrapObservable(item[prop]);
if (key) {
propIndex[key] = propIndex[key] || [];
propIndex[key].push(item);
}
});
target.index[prop](propIndex);
});
return target;
};
var Person = function(name, type) {
this.name = ko.observable(name);
this.type = ko.observable(type);
}
var ViewModel = function() {
var self = this;
this.choices = ["Friend", "Enemy", "Other" ];
this.people = ko.observableArray([
new Person("Jimmy", "Friend"),
new Person("George", "Friend"),
new Person("Zippy", "Enemy")
]).distinct('type');
this.addPerson = function() {
self.people.push(new Person("new", "Other"));
};
this.removePerson = function(person) {
self.people.remove(person);
};
};
ko.applyBindings(new ViewModel());