Knockout binding with a customization in for each

后端 未结 1 989
[愿得一人]
[愿得一人] 2021-01-29 03:26

I have a situation here for the knockout with for each binding with customization

Here is my code:

相关标签:
1条回答
  • 2021-01-29 03:49

    You could create a computed which would pair items, something like the following:

    self.rows = ko.computed(function(){
        var allItems = self.resultData();
        var rows = [];
        for(var i = 0, len = allItems.length; i < len; i = i+2){
            rows.push({
                leftItem: allItems[i],
                rightItem: i + 1 < len ? allItems[i + 1] : null
            });
        }
        return rows;
    });
    

    You would then bind to the rows property instead of binding directly to the resultData property.

    EDIT: @GOK asked, in a comment, for a version which would allow customizable number of items in a single row.

    You could achieve this easily by doing something like the following:

    self.itemsOnEachRow = ko.observable(2);
    self.rows = ko.computed(function(){
        var allItems = self.resultData();
        var itemsPerRow = self.itemsOnEachRow();
        var rows = [];
        for(var i = 0, len = allItems.length; i < len; i = i + itemsPerRow){
            var row = {};
            for(var itemIndex = 0; itemIndex < itemsPerRow; itemIndex++){
                var item = null;
                if (i + itemIndex < len){
                    item = allItems[i + itemIndex];
                }
                row['item' + itemIndex] = item;
            }
            rows.push(row);
        }
        return rows;
    });
    

    Each row would then have properties named item1, item2, etc, to the number of items set by the itemsOnEachRow observable (some of these properties might hold a null reference, if the total item count isn't evenly divisible by the items per row count).

    I have written a sample on this, which you can find on http://jsfiddle.net/af7P2/, but I do not suggest binding the table in the way it is done in that sample. I'm not sure how it would set up subscriptions, but it might subscribe a multitude of times to the columns computed, one time for each row. It's just there to show a sample of the rows computed, not for anything else.

    If you want each row to be an array in itself, you could do it with the following code:

    self.itemsOnEachRow = ko.observable(2);
    self.rows = ko.computed(function(){
        var allItems = self.resultData();
        var itemsPerRow = self.itemsOnEachRow();
        var rows = [];
        for(var i = 0, len = allItems.length; i < len; i = i + itemsPerRow){
            var row = [];
            for(var itemIndex = 0; itemIndex < itemsPerRow; itemIndex++){
                var item = null;
                if (i + itemIndex < len){
                    item = allItems[i + itemIndex];
                }
                row.push(item);
            }
            rows.push(row);
        }
        return rows;
    });
    

    The bindings for this version (which you can find at http://jsfiddle.net/af7P2/1/) is a bit better, since it doesn't use the columns computed one time for each row.

    In general, this solution might not perform very well, depending on your situation. Any addition/removal of items to the resultData array, or a change to the itemsOnEachRow value, would rebind the whole table. Might not be a problem for you, just something to be aware of.

    0 讨论(0)
提交回复
热议问题