我得到了一堆文档。该文档有一些类别,并且按类别排序。对于每个类别,我希望有一个标题,例如: - 运动 --- 体育文件 1 --- 体育文献2 --- 体育文献3 - 锦标赛 --- 比赛文件 1 --- 锦标赛文件 2 --- 锦标赛文档 3
因此“体育”和“锦标赛”类别是标题。
我的问题是我不知道如何使用此标题创建一个新的 Div 来获得列表。
我当前的代码
var DocumentRow = function (documentLine) {
var self = this;
// getting name and ID of the document
self.Name = ko.observable(documentLine.Name);
self.DocumentId = ko.observable(documentLine.DocumentId);
// creating downloadLink
self.DocumentLink = ko.computed(function () {
return "someUrlPath/read/import/" + self.DocumentId();
});
}
GetCustomerDocuments(data.SomeID)
.done(function (data) {
// Reset Documents from Previous View
self.documentLines([]);
// Only mapping when it has some data
if (data !== null && data !== undefined && data.length > 0) {
// loop trought the arry
self.documentLines(data.map(function (doc) {
return new DocumentRow(doc);
}));
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="foreach: documentLines">
<div class="importDocument">
<a data-bind="attr: {href: DocumentLink}, target:'_blank'">
<span data-bind="target:'_blank'">
<img src="../images/pdf.png" title="Document" />
</span>
<span data-bind="text: Name, target:'_blank'" title="Document"></span>
</a>
</div>
</div>
最佳答案
生成易于阅读的数据绑定(bind)的干净解决方案是创建一个 ko.compulated
,为您的数据添加分组层。您将创建此结构:
- 文档行
- 文档组
- 文档行
- 文档行
- ...
- 文档组
- ...
- 文档组
计算使用您的 documentLines
数组作为起点,为它遇到的每个唯一的 Category
创建一个组,并将与该类别匹配的文档推送到该组。
您尚未显示实际的 Category
属性,因此我假设它是每个 documentRow
内的字符串属性。
下面的代码向您展示了分组计算如何工作的示例。查看评论以了解所发生情况的解释。按属性对对象进行分组是很常见的事情,stackoverflow 上应该有许多其他示例向您展示如何进行操作。这是更多关于 knockout 如何运作的内容:
var VM = function() {
var self = this;
// This is our data source
self.documentRows = ko.observableArray([]);
// This injects a group layer and will be used in our foreach:
self.docGroups = ko.pureComputed(function() {
// This creates a subscription that makes sure the object is updated
// every time the documentRows are updated
var rows = self.documentRows();
// Grouping logic:
// create an object of: { "CategoryName": [ /* documentRows*/ ] }
var categoryMap = rows.reduce(function(map, row) {
var category = row.Category;
map[category] = map[category] || [];
map[category].push(row);
return map;
}, {});
// Transform to object and sort by name
return Object.keys(categoryMap)
.map(function(k) {
return { name: k, rows: categoryMap[k] }
})
.sort(function(c1, c2) {
return c1.name.localeCompare(c2.name);
});
});
}
var vm = new VM();
ko.applyBindings(vm);
vm.documentRows.push({Category: "Cat1", Text: "The First Document"});
vm.documentRows.push({Category: "Cat2", Text: "The Second Document"});
vm.documentRows.push({Category: "Cat2", Text: "The Second 2nd Document"});
vm.documentRows.push({Category: "Another category", Text: "The Third Document"});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<h2>Categories:</h2>
<ul data-bind="foreach: docGroups">
<li>
<h3 data-bind="text: name"></h3>
<ul data-bind="foreach: rows">
<li data-bind="text: Text"></li>
</ul>
</li>
</ul>
其他方法:
如果您不想要嵌套结构,您还可以创建一个包含两种类型对象的平面列表:文档和组。您必须使用 if
或 template
绑定(bind)来确定您希望其呈现的方式。
如果您确定数据是按分组属性排序的,您可以通过检查 $parent.documentLines( )[$index() - 1].Category === $data.Category
,但我强烈建议不要这样做...
关于javascript - 使用knout js在foreach中添加类别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41632414/