如何在搜索条件中包含子数组?

时间:2015-12-01 16:44:13

标签: javascript arrays knockout.js

var Foo = function() {
  var self = this;
  self.name = ko.observable();
  self.age = ko.observable();
  self.gender = ko.observable();
  self.childs = ko.observableArray([]);
};

var Child = function() {
  var self = this;
  self.childName = ko.observable();
};

var data = [
  { name: 'Foo1', age: 21, gender: 'Male', childs: [{ name: 'Child1' }, { name: 'AnotherChild1' }] },
  { name: 'Foo2', age: 22, gender: 'Female', childs: [{ name: 'Child2' }, { name: 'AnotherChild2' }] },
  { name: 'Foo3', age: 23, gender: 'Male', childs: [{ name: 'AnotherChild3' }] },
  ];

var vm = (function() {
  var foos = ko.observableArray([]),
      init = function() {
        for(var i = 0;i < data.length; i++) {
          var newFoo = new Foo()
                    .name(data[i].name)
                    .age(data[i].age)
                    .gender(data[i].gender);
          
          for(var j = 0; j < data[i].childs.length; j++) {
            newFoo.childs.push(new Child()
                             .childName(data[i].childs[j].name));
          }
          
          foos.push(newFoo);
        }
      },
      startsWith = function (str, prefix) {
        if(str) return (!prefix || str.slice(0, prefix.length).toLowerCase() === prefix.toLowerCase())
        return;
      },
      searchTerm = ko.observable(),
      filterFoos = ko.computed(function() {
        return ko.utils.arrayFilter(foos(), function(item) {
          return (startsWith(item.name(), searchTerm()));
        });
      });
  
  return {
    foos: foos,
    init: init,
    searchTerm: searchTerm,
    filterFoos: filterFoos
  }
}());


vm.init();
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="text" data-bind="value: $root.searchTerm" />
<span data-bind="text: $root.searchTerm"></span>
<pre data-bind="text: ko.toJSON($root.searchTerm, null, 2)"></pre>
<pre data-bind="text: ko.toJSON($root.filterFoos, null, 2)"></pre>

我上面的代码片段运行并查看是否有任何搜索条件。现在,我如何在搜索条件中包含childs数组?我想知道如果我在文本框中输入值,它还会查看childs数组以查看它是否存在。

如果我需要进一步澄清事情,请告诉我

非常感谢任何帮助。感谢

1 个答案:

答案 0 :(得分:1)

添加了递归以搜索项目的所有子项

var Foo = function() {
  var self = this;
  self.name = ko.observable();
  self.age = ko.observable();
  self.gender = ko.observable();
  self.childs = ko.observableArray([]);
};

var Child = function() {
  var self = this;
  self.childName = ko.observable();
};

var data = [
  { name: 'Foo1', age: 21, gender: 'Male', childs: [{ name: 'Child1' }, { name: 'AnotherChild1' }] },
  { name: 'Foo2', age: 22, gender: 'Female', childs: [{ name: 'Child2' }, { name: 'AnotherChild2' }] },
  { name: 'Foo3', age: 23, gender: 'Male', childs: [{ name: 'AnotherChild3' }] },
  ];

var vm = (function() {
  var foos = ko.observableArray([]),
      init = function() {
        for(var i = 0;i < data.length; i++) {
          var newFoo = new Foo()
                    .name(data[i].name)
                    .age(data[i].age)
                    .gender(data[i].gender);
          
          for(var j = 0; j < data[i].childs.length; j++) {
            newFoo.childs.push(new Child()
                             .childName(data[i].childs[j].name));
          }
          
          foos.push(newFoo);
        }
      },
      startsWith = function (item, prefix) {
var str = item.name? item.name():item.childName();
        if(str) return (!prefix || str.slice(0, prefix.length).toLowerCase() === prefix.toLowerCase()) || 
(item.childs && ko.utils.arrayFilter(item.childs(),function(child){
return startsWith(child,prefix);
}).length>0);
        return;
      },
      searchTerm = ko.observable(),
      filterFoos = ko.computed(function() {
        return ko.utils.arrayFilter(foos(), function(item) {
          return (startsWith(item, searchTerm()));
        });
      });
  
  return {
    foos: foos,
    init: init,
    searchTerm: searchTerm,
    filterFoos: filterFoos
  }
}());


vm.init();
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="text" data-bind="value: $root.searchTerm" />
<span data-bind="text: $root.searchTerm"></span>
<pre data-bind="text: ko.toJSON($root.searchTerm, null, 2)"></pre>
<pre data-bind="text: ko.toJSON($root.filterFoos, null, 2)"></pre>