Knockout.JS: AsDictionary

http://www.wiredprairie.us/blog/index.php/archives/1563

by rniemeyer

HTML

<script src="http://knockoutjs.com/downloads/knockout-2.0.0.debug.js"></script>
<ul data-bind="foreach: items">
    <li>
        <span data-bind="text: name"></span>
        <a href="#" data-bind="click: $root.items.remove.bind($root.items)"> x </a>
    </li>
</ul>

<button data-bind="click: addItem">Add Item</button>
    
<hr/>
    
<pre data-bind="text: JSON.stringify(ko.toJS(items.index), null, 2)"></pre>

CSS

td { padding: 2px; }

JavaScript

ko.observableArray.fn.indexBy = function (keyName) {
    this.index = ko.computed(function () {
        var list = this() || [];
        var keys = {}; 
        ko.utils.arrayForEach(list, function (v) {
            if (keyName) {          
                keys[v[keyName]] = v;   
            } else {
                keys[v] = v;
            }
        });
        return keys;
    }, this);
    
    return this;
};

ko.observableArray.fn.findByKey = function(key) {
     return this.index[key];
};

var ViewModel = function () {
    var count = 0;
    
    this.items = ko.observableArray([]).indexBy("id");
    
    this.addItem = function() {
        this.items.push({ id: ++count, name: "item " + count });   
    };
    
    this.removeItem = function(item) {
        this.items.remove(item);   
    }.bind(this);
};

ko.applyBindings(new ViewModel());