Bind template item to the index of the array in Kn

2020-02-09 09:21发布

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.

3条回答
beautiful°
2楼-- · 2020-02-09 10:15

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/

查看更多
SAY GOODBYE
3楼-- · 2020-02-09 10:19

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!

查看更多
男人必须洒脱
4楼-- · 2020-02-09 10:19

Had the same problem but with a dependantObservable as source for the foreach template, alas the ko.utils.arrayIndexOf didn't work...

Solution: created a function that recreated the array returned by the dependantObservable and simply used the js indexOf function with the Item:

arrayIndexDO: function (item) {
    var filteredArray = ko.utils.arrayFilter(viewModel.someObservableArray(), function (element) {
        return element.id() == view.selectedId();
    });
    var index = filteredArray.indexOf(item);
    return index;
}

Et voilà, the expected index in the jQuery tpl.

查看更多
登录 后发表回答