Unique ids in knockout.js templates

An alternative that does not rely on the order that the fields are bound is to have the binding set an id property on the data itself, which would need to be an observable.

ko.bindingHandlers.uniqueId = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);

        element.id = value.id;
    },
    counter: 0,
    prefix: "unique"
};

ko.bindingHandlers.uniqueFor = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);

        element.setAttribute("for", value.id);
    } 
};

You would use it like:

<ul data-bind="foreach: items">
    <li>
        <label data-bind="uniqueFor: name">Before</label>
        <input data-bind="uniqueId: name, value: name" />
        <label data-bind="uniqueFor: name">After</label>
    </li>
</ul>

Sample: http://jsfiddle.net/rniemeyer/JjBhY/

The nice thing about adding a property to the observable function is that when you turn it into JSON to send back to the server, then it will just naturally disappear as the observable will just turn into its unwrapped value.

Leave a Comment