使用Knockout JS搜索嵌套json数组的过滤器

时间:2017-03-04 13:34:16

标签: javascript json knockout.js

我试图使用Knockout js过滤嵌套的json数组。以下是我的JSON外观

{
"groups": [{
    "name": "Category1",
    "items": [{
        "question": "Question1",
        "answer": "Answer1"
    }]
}, {
    "name": "Category2",
    "items": [{
        "question": "Question2",
        "answer": "Answer2"
    }, {
        "question": "Question3",
        "answer": "Answer3"
    }]
  }]
}

我需要根据“答案”进行过滤。以下是我的HTML页面现在的样子

 <div >
<div class="groups" data-bind="{foreach: {data: filteredGroups, as: 'group'}}">
  <div class="name-row" data-bind="text: group.name"></div>
  <div class="items" data-bind="{foreach: {data: group.items, as: 'item'}}">
    <div class="item-row">
      <div class="question-row">
        <div class="question-content">
          <div class="letter">Question</div>
          <div data-bind="text: item.question"></div>
        </div>
        <div class="notch">&nbsp;</div>
      </div>
      <div class="answer-row">
        <div class="letter">Answer</div>
        <div data-bind="text: item.answer"></div>
      </div>
    </div>
  </div>
</div>

以下是我目前的逻辑:

 self.filteredGroups = ko.computed(function() {
  if (!self.query()) {
    return self.groups();
  }
  else {  

       var matchCount = 0;

      return ko.utils.arrayFilter(self.groups(), function(group) {
        return ko.utils.arrayFilter(group.items, function(item) { 
           //console.log("Entered==>" + self.query().toLowerCase() +  "  "  + "Search==>" + item.question.toLowerCase());
           var found = item.answer.toLowerCase().indexOf(self.query().toLowerCase());
           if(found >= 0){
             console.log("Number of occurrences" +matchCount++);
             return true;
           }else{
             return false;
           }
         });
      });

   }
});

然而,当我尝试执行相同的操作时,我没有得到过滤结果。有什么我想念的吗?

1 个答案:

答案 0 :(得分:3)

我想你想要保留他们的小组来过滤项目。在您的解决方案中,内部arrayFilter将始终返回一组过滤的项目。但是你可能知道任何数组(甚至是空的)总是会评估为true,导致外部arrayFilter使用 all 返回所有原始组对象原始项目,因为过滤的项目由于隐式类型转换而丢失。

computed工作的最简单方法:

self.filteredGroups = ko.computed(function() {
    if (!self.query()) {
        return self.groups();
    } else {

        var result = [];

        // for each group
        ko.utils.arrayForEach(self.groups(), function(group){

            // find items matching the query
            var items = ko.utils.arrayFilter(group.items, function(item){
                return item.answer.toLowerCase().indexOf(self.query()) >= 0;
            }); console.log(items);

            // if found something then push new group object with filtered items
            if (items.length > 0) result.push({
                name: group.name,
                items: items
            });

        });

        return result;
    }
});

fiddle