【问题标题】:Angular custom filter to complex object复杂对象的角度自定义过滤器
【发布时间】:2017-01-17 21:07:48
【问题描述】:

我有一个 $scope.users 用于显示表格,我需要应用具有多个选项的过滤器,

这里是$scope.users 对象:

[
  {
    "login": "andres.un1@mail.com",
    "merchant": {
      "merchantId": 500095,
      "status": "ENABLED",
      "defaultAccountId": null,
      "accounts": {
        "500092": "ADMIN",
        "500178": "CONSULT",
        "500180": "ADMIN",
        "500182": "ADMIN",
        "500201": "ADMIN"
      }
    },    
    "name": "Carlos"    
  },
  {
    "login": "andres.un2@mail.com",
    "merchant": {
      "merchantId": 500095,
      "status": "DISABLED",
      "defaultAccountId": null,
      "accounts": {
        "500092": "CONSULT",
        "500178": "MANAGER",
        "500180": "ADMIN",
        "500182": "ADMIN",
        "500201": "ADMIN"
      }
    },
    "name": "Carlos Andres"
  },
  {
    "login": "cosme.fulanito@mail.com",
    "merchant": {
      "merchantId": 500095,
      "status": "DISABLED",
      "defaultAccountId": null,
      "accounts": {
        "500092": "CONSULT",
        "500178": "MANAGER",
        "500180": "ADMIN",
        "500182": "ADMIN",
        "500201": "ADMIN"
      }
    },
    "name": "Cosme"    
  }
]

在过滤器中,我从$scope 传递其他对象来过滤数据,在本例中是我之前在指令中计算的$scope.searchParams

$scope.searchParams:

[
  {'name':'Cosme'},
  {'login':'andres.un1@mail.com'},
  {'status':'ENABLED'},
  {'status':'DISABLED'},
  {'account':'267123'},
  {'account':'543987'},
  {'account':'544111'},
  {'account':'543987'}
]

如您所见,namelogin 在过滤器中是唯一的,但 statusaccount 可以在过滤器中应用多个值。这是我的方法,但我认为非常无效,也不完整,因为没有多重过滤器功能:

var secUser = function () {

  return function (input, list) {

    var out = [];

    var nameArr = [],
      loginArr = [],
      statusArr = [],
      profileArr = [],
      accountsArr = [];

    angular.forEach(list, function(filter){
      console.log(filter);
      if(filter.hasOwnProperty('name')){
        nameArr.push(filter.name);
      }
      if(filter.hasOwnProperty('login')){
        loginArr.push(filter.login);
      }
      if(filter.hasOwnProperty('status')){
        statusArr.push(filter.status);
      }
      if(filter.hasOwnProperty('account')){
        accountsArr.push(filter.account);
      }
      if(filter.hasOwnProperty('profile')){
        profileArr.push(filter.profile);
      }
    });

    angular.forEach(input, function(user){

      // no filters applied
      if(nameArr.length < 1 && loginArr.length < 1 &&
        statusArr.length < 1 && accountsArr.length < 1 &&
        profileArr.length < 1){
        out.push(user);
      }
      // filters to be applied
      else{
        if(nameArr.indexOf(user.name) > -1){
          out.push(user);
        }
        if(loginArr.indexOf(user.login) > -1){
          out.push(user);
        }
        if(statusArr.indexOf(user.merchant.status) > -1){
          out.push(user);
        }
      }

    });

    return out;
  };
};
//-- register filter
app.filter('secUser', secUser);

最后这里是我使用 fiter 的方法:&lt;tbody ng-repeat="user in users | secUser:searchParams " class="table-striped"&gt;

¿考虑到将来可能会有更多过滤器字段,是否有更好的方法来实现此过滤器?另外我认为是非常耦合的观点。

【问题讨论】:

    标签: javascript angularjs filter


    【解决方案1】:

    有多种方法可以做到这一点,但一个要求是您需要使您的searchParams 结构更通用。例如,这里我使用一个对象,其中每个键是目标对象的路径,对应的值是一个数组,其中包含您要匹配的所有值:

    $scope.searchParams = {
      'name': ['Cosme'],
      'login': ['andres.un1@mail.com'],
      'merchant.status' : ['ENABLED','DISABLED'],
      'merchant.accounts' : ['267123','543987 ','544111','543987'],
    }
    

    然后您可以更新过滤器以处理通用数据。它不能完全通用,因为它确实取决于您的业务逻辑,例如accounts 是否匹配键 500092 或值 CONSULT。这是一个更新的过滤器函数,用于处理数据中的三种目标:

    • 原始值与值匹配,例如name
    • 数组匹配任何内容,例如status
    • 对象匹配任何键,例如accounts

    JsFiddle(数据稍作修改以供测试)

    var secUser = function () {
      return function (users, filters) {
    
        return users.filter(function(user){
          var match = false;
    
          angular.forEach(filters, function(filterValues, keyPath){
            if (match) return; // if we already found a match, don't continue searching
    
            // get the target based on the contents of the keypath
            var target = keyPath.split('.').reduce(function(object, key) {
              // get the next part of the path, if exists
              return object && object[key];
            }, user); // initial value is the user object
    
            if (target !== undefined){ // if the target exists for this item
              var values = []; // stores the values from the item to search against
    
              if(typeof target === "object") {
                values = Object.keys(target);            
              }
              else if (target.isArray) {
                values = target;
              } else {
                values = [target];
              }
    
              // check if any entry in values matches any entry of the filter values
              match = values.some(function (v) {
                return filterValues.indexOf(v) >= 0;
              });
            }
          });
    
          return match;
        });
      };
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-27
      • 2019-02-16
      • 2015-04-17
      • 2017-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多