I need to name the <div>'s in a KnockoutJS template according to the position that they appear in the list for a Jquery plugin like so:
<div id="item1">...</div>
<div id="item2">...</div>
<div id="item3">...</div>
Is there a way to bind to the index of the item in the array using KnockoutJS? It would be a shame if I had to add this data to the select on the database using ROWINDEX.
update: KO now supports a $index context variable that you can use within a foreach (or template with foreach param). Docs: http://knockoutjs.com/documentation/binding-context.html
If you are okay with using jQuery Templates {{each}}, then something like this will work:
<div data-bind="template: 'allItemsTmpl'"></div>
<script id="allItemsTmpl" type="text/html">
{{each(i, item) items}}
<div data-bind="attr: { id: 'item' + i }">
<input data-bind="value: name" />
</div>
{{/each}}
</script>
If you had to use the foreach option, then something like this would work:
<div data-bind="template: { name: 'itemTmpl', foreach: items }"></div>
<button data-bind="click: addItem">Add Item</button>
<script id="itemTmpl" type="text/html">
<div data-bind="attr: { id: 'item' + ko.utils.arrayIndexOf(viewModel.items, $data) }">
<input data-bind="value: name" />
</div>
</script>
Edit: these days I prefer to create a subscription to my observableArray that only has to take one pass through the array and create/set an index observable on the item. Like:
//attach index to items whenever array changes
viewModel.tasks.subscribe(function() {
var tasks = this.tasks();
for (var i = 0, j = tasks.length; i < j; i++) {
var task = tasks[i];
if (!task.index) {
task.index = ko.observable(i);
} else {
task.index(i);
}
}
}, viewModel);
Sample here: http://jsfiddle.net/rniemeyer/CXBFN/
or you can take this idea and extend observableArrays to provide an indexed function that would allow you to set this up just by calling myObservableArray.indexed().
Here is a sample: http://jsfiddle.net/rniemeyer/nEgqY/
This is much easier with Knockout 2.1.0 and above:
<div data-bind="foreach: items">
<div data-bind="attr: { id : 'item' + $index() }"></div>
</div>
No fancy scripts necessary.
A word of caution: attr: { id : 'item' + $index } will NOT work. Since $index is a function itself, failing to add the parentheses will cause your id to be the concatenation of 'item' and the entire function definition!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With