有没有办法从Knockout foreach
绑定中手动增加ViewModel属性?
我想做一些逻辑上等同于:
的事情var inc = 0;
for (var i = 0; i < 3; i++)
{
for (var j = 0; j < 3; j++)
{
inc++;
alert(inc + ': ' + i + ',' + j); // but write this to the dom
}
}
我曾尝试使用$index
,但这只涉及当前循环,而不是内循环或父循环。
数组的大小可能不同,所以我不能简单地计算$parentContext.$index * [count of child items] + current $index
。
我想要实现的目标:
<div data-bind="foreach: Categories">
<div data-bind="foreach: SubCategories" >
<div data-bind="text: [someIncrementer] +': ' + $parent.Category + ',' + $data></div>
<!-- should output:
1: A,1
2: A,2
3: A,3
4: B,1
5: B,3
-->
</div>
</div>
var ViewModel = function()
{
var self = this;
self.Categories = ko.observableArray([
{Category: 'A', SubCategories: [1,2,3]},
{Category: 'B', SubCategories: [1,3]}
]);
}
答案 0 :(得分:2)
为其创建一个带有展平数组的计算observable:
var ViewModel = function() {
var self = this;
self.Categories = ko.observableArray([
{Category: 'A', SubCategories: [1,2,3]},
{Category: 'B', SubCategories: [1,3]}
]);
self.FlattenedSubcategories = ko.computed(function() {
var result = [], cats = self.Categories(), index = 1;
for (var i = 0; i < cats.length; i++) {
for (var j = 0; j < cats[i].SubCategories.length; j++) {
result.push({
Idx: index++,
Category: cats[i].Category,
Subcat: cats[i].SubCategories[j]
});
}
}
return result;
});
};
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<div data-bind="foreach: FlattenedSubcategories">
<div>
<span data-bind="text: Idx"></span>:
<span data-bind="text: Category"></span>,
<span data-bind="text: Subcat"></span>
</div>
</div>
答案 1 :(得分:2)
不需要让它变得复杂得多。你可以尝试这样的事情:
var ViewModel = function() {
var self = this;
var index = 0;
self.inc = function(val) {
return ++index;
}
self.Categories = ko.observableArray([{
Category: 'A',
SubCategories: [1, 2, 3]
}, {
Category: 'B',
SubCategories: [1, 3]
}]);
};
ko.applyBindings(new ViewModel());
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: Categories">
<!-- ko foreach: SubCategories -->
<li>
<span data-bind="text: $root.inc() + ': ' + $parent.Category + ', ' + $data"></span>
</li>
<!-- /ko -->
</ul>
&#13;
答案 2 :(得分:1)
您可以将<ol>
/ <li>
与数字计数器或CSS counter一起使用。
如果数字纯粹用于显示目的而且没有任何依赖于它,则此方法有效。
var ViewModel = function()
{
var self = this;
self.Categories = ko.observableArray([
{Category: 'A', SubCategories: [1,2,3]},
{Category: 'B', SubCategories: [1,3]},
{Category: 'C', SubCategories: [7,8,9]},
{Category: 'D', SubCategories: [10,11,12,13]}
]);
}
ko.applyBindings(new ViewModel());
.categories {
counter-reset: category;
}
.subcategory::before {
counter-increment: category;
content: counter(category) ": ";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="categories" data-bind="foreach: Categories">
<div data-bind="foreach: SubCategories">
<div>
<span class="subcategory" data-bind="text: $parent.Category + ',' + $data"></span>
</div>
</div>
</div>
答案 3 :(得分:0)
另一种选择:
就像你说的那样,knockout绑定上下文暴露了一个$index
observable,它将索引保存在循环中。还有$parentContext
来指代链中较高的上下文。
对于一个简单的2级嵌套循环,您可以创建一个帮助方法,该方法使用当前$index
和父级$index
来计算总索引:
// cIndex = current category's index
// sIndex = current subcategory's index
self.getSubIndex = function(cIndex, sIndex) {
return sIndex + self.Categories
.slice(0, cIndex)
.reduce(function(count, c) {
return count + c.SubCategories.length;
}, 0);
}
写一下会有点烦人:
<span data-bind="text: $root.getSubIndex($parentContext.$index(), $index())"> </span>
您也可以传递$context
并获取getSubIndex
方法中的索引。您甚至可以递归地浏览上下文链,直到找不到$index
属性为止。
就个人而言,我宁愿在index
视图模型中创建一个SubCategory
计算器,这会让人感觉不那么笨拙。但是,它需要SubCategory
才能访问其父...
var ViewModel = function() {
var self = this;
self.Categories = ko.observableArray([{
Category: 'A',
SubCategories: [1, 2, 3]
}, {
Category: 'B',
SubCategories: [1, 3]
}]);
self.getSubIndex = function(cIndex, sIndex) {
return sIndex + self.Categories
.slice(0, cIndex)
.reduce(function(count, c) {
return count + c.SubCategories.length;
}, 0);
}
};
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: Categories">
<!-- ko foreach: SubCategories -->
<li>
<span data-bind="text: $root.getSubIndex($parentContext.$index(), $index()) + ': ' + $parent.Category + ', ' + $data"></span>
</li>
<!-- /ko -->
</ul>