Suppose I have knockout.js template like this:
<script type="text/html" id="mytemplate">
<label for="inputId">Label for input</label>
<input type="text" id="inputId" data-bind="value: inputValue"/>
</script>
If I render this template in several places on the page I end up with several inputs with the same id (and several labels with the same for value), which has bad consequences. In particular, all code that depends on ids may not work properly (in my case I use jquery.infieldlabel plugin that gets confused by multiple inputs with the same id). The way I solve this issue now is I add unique id attribute to the model that I bind to the template:
<script type="text/html" id="mytemplate">
<label data-bind="attr: {for: id}>Label for input</label>
<input type="text" data-bind="attr: {id: id}, value: inputValue"/>
</script>
This works, but it's not very elegant since I have to have this artificial id attribute in my models that is not used for anything else. I wonder if there is a better solution here.
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.You would use it like:
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.
I can't reply to the selected answer, but I have an enhanced version of the code that supports multiple unique ids per input value. It's on my blog at http://drewp.quickwitretort.com/2012/09/18/0 and repeated here:
Now you can have multiple labeled checkboxes for one record with automatic ids:
I have done something like this in the past:
You would use them like:
So, it just keeps state on the binding itself incrementing
ko.bindingHandlers.uniqueId.counter
. Then, theuniqueFor
binding just needs to know whether it is before or after the field to know how to get the correct id.Sample here: http://jsfiddle.net/rniemeyer/8KJD3/
If your labels were not near their fields (multiple inputs bound before each label perhaps in separate rows of a table), then you would need to look at a different strategy.