javascript - 使用knout js在foreach中添加类别

标签 javascript html knockout.js

我得到了一堆文档。该文档有一些类别,并且按类别排序。对于每个类别,我希望有一个标题,例如: - 运动 --- 体育文件 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 ,为您的数据添加分组层。您将创建此结构:

  • 文档行
    • 文档组
      1. 文档行
      2. 文档行
      3. ...
    • 文档组
    • ...

计算使用您的 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>
                   

其他方法:

如果您不想要嵌套结构,您还可以创建一个包含两种类型对象的平面列表:文档和组。您必须使用 iftemplate 绑定(bind)来确定您希望其呈现的方式。

如果您确定数据是按分组属性排序的,您可以通过检查 $parent.documentLines( )[$index() - 1].Category === $data.Category,但我强烈建议不要这样做...

关于javascript - 使用knout js在foreach中添加类别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41632414/

相关文章:

javascript - 为什么 v-model 不显示?需要在表单处于编辑模式时显示值

javascript - 使用 jQuery Mobile 风格动态添加文本框

javascript - 显示比较表

asp.net-mvc-3 - 将 MVVM 与 Knockout.js 结合使用时在服务器端定义模型

javascript - 如何在窗口加载后加载图像?

javascript - 原型(prototype)中的 jQuery.active($.active) 相当于什么

php - PHP/JavaScript/CSS 需要解析器精度吗?

Javascript,在确认窗口中按“确定”后清除表格。但如果取消确认,则保留表单数据

html - 制作将堆叠到右侧的瓷砖

knockout.js - knockout 2 级数组中的多个 foreach