如何编写一个过滤器来搜索角度的嵌套json?

时间:2016-11-27 11:43:19

标签: angularjs angular-filters

我使用ui-select以角度编写了一个小程序。我想编写一个过滤器,在不同的字段中执行 OR 搜索(可以是json中的嵌套字段)。在ui-select的github中,我发现这个过滤器可以做类似的事情(但只有简单的字段):

/**
 * AngularJS default filter with the following expression:
 * "person in people | filter: {name: $select.search, age: $select.search}"
 * performs an AND between 'name: $select.search' and 'age: $select.search'.
 * We want to perform an OR.
 */
app.filter('propsFilter', function() {
  return function(items, props) {
    var out = [];

    if (angular.isArray(items)) {
      var keys = Object.keys(props);

      items.forEach(function(item) {
        var itemMatches = false;

        for (var i = 0; i < keys.length; i++) {
          var prop = keys[i];
          var text = props[prop].toLowerCase();
          if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
            itemMatches = true;
            break;
          }
        }

        if (itemMatches) {
          out.push(item);
        }
      });
    } else {
      // Let the output be the input untouched
      out = items;
    }

    return out;
  };
});

我想要应用此过滤器的json对象具有以下结构:

$scope.contracts = [{
  name: "contract1.00",
  value: 10,
  id :{
    id : 8000,
    code : 2
  },
  policy : {
    info : {
      name : "test1",
      country : "test"
    }
  }
}
//other elements....

问题是这个'propsFilter'只适用于简单的字段。所以,如果我写这个:

 propsFilter: {name: $select.search, value : $select.search}

它将正确工作并在这两个字段(名称OR值)中进行OR搜索。但在我的例子中,我想用另外两个字段进行OR搜索:id.id和policy.info.name。

所以,我想要做的是使用这样的一行:

propsFilter: {name: $select.search, value : $select.search, id.id : $select.search, policy.info.name : $select.search }

最后,这是我的傻瓜:http://plnkr.co/edit/ej2r7XqeTPOC5d1NDXJn?p=preview

如何在同一搜索过滤器中执行此操作?

1 个答案:

答案 0 :(得分:0)

我已经更新了你的plunker。首先,从循环中断导致过滤器仅在第一个属性name上工作,我还在if item[prop] &&中添加了一个条件,因此您的代码在属性时不会抛出错误项目上不存在

http://plnkr.co/edit/CwNANzodvjnuMCNyJYtA?p=preview

app.filter('propsFilter', function($parse) {
  return function(items, props) {
    var out = [];

    if (angular.isArray(items)) {
      var keys = Object.keys(props);

      items.forEach(function(item) {
        var itemMatches = false;

        for (var i = 0; i < keys.length; i++) {
          var prop = $parse(keys[i])(item);
          var text = props[keys[i]].toLowerCase();

          if (prop && prop.toString().toLowerCase().indexOf(text) !== -1) {
            itemMatches = true;
          }
        }

        if (itemMatches) {
          out.push(item);
        }
      });
    } else {
      // Let the output be the input untouched
      out = items;
    }

    return out;
  };
});