【问题标题】:How to use angular filter on multiple properties of the object如何在对象的多个属性上使用角度过滤器
【发布时间】:2016-08-06 03:10:55
【问题描述】:

我有一个这样的简单 ng-repeat:

<input type="text" ng-model="vm.filter">

<div ng-repeat="tenant in vm.tenants | filter : vm.filter : vm.contains">
 </div>

现在我想根据过滤器的值过滤租户,例如查找租户名称是否包含类似的过滤器表达式

function contains(actual, expected) {
            return actual.name.indexOf(expected) >= 0;
        }

我不明白为什么我在 contains 函数中得到一个 tenant.name 而不是 tenant 本身。我知道对于一个简单的情况,我可以执行filter | {name: vm.filter} | vm.contains 之类的操作,但如果我想基于多个属性(例如姓名、电话等)进行过滤,该怎么办

【问题讨论】:

    标签: javascript angularjs angular-filters


    【解决方案1】:

    我不明白为什么我在 contains 中得到了一个tenant.name 函数而不是租户本身。

    发生的情况是 Angular 提供了对象的所有级别的比较器,以尝试进行深度过滤,即它尝试将您的过滤器与对象中的所有层次结构级别匹配。如果你 console.log 所有的值,你会看到你也得到了完整的对象(在所有属性之后)。


    完成这项工作的一种方法是

    ...
    <div ng-repeat="tenant in vm.tenants | filter : vm.contains(vm.filter)">
    ...
    

    然后

    ...
    contains: function(filter) {
      return function(tenant) {
        return tenant.name.indexOf(filter) !== -1;
      }
    }
    ...
    

    小提琴 - https://jsfiddle.net/81384sd7/

    【讨论】:

    • 是的,我通过调试发现它正在进行深度比较。有没有办法不这样做?我想根据对象本身在提供的函数中使用我的自定义逻辑,但由于某种原因似乎不可能
    • 您可以将您的过滤功能作为第一个参数进行过滤并直接使用范围中的 vm.filter 或执行类似jsfiddle.net/u9rq7afk 的操作(输入abc 以获得2个匹配的租户)
    • 是的,谢谢,这似乎可以解决问题,我错过了表达式参数可以接受函数本身。
    【解决方案2】:

    您可以使用对象来存储要应用的过滤器。例如:

    $scope.filterBy = {
      name: "Bob",
      phone: "07"
    };
    

    然后配置字段以编辑过滤器:

    <input type="text" ng-model="filterBy.name" />
    <input type="text" ng-model="filterBy.phone" />
    

    然后只过滤这个对象。

    <div ng-repeat="tenant in vm.tenants | filter : filterBy">
    

    看看我之前的答案,它非常相似,除了还允许在使用按钮手动应用过滤器之前进行选择:

    Applying a angularjs filter after "Apply" button click

    我希望这会有所帮助。

    【讨论】:

    • 虽然如果我创建一个带有重复字符串的特制对象,这可能会起作用,但我真的希望相同的字符串与一个对象的各种属性相匹配。
    • 所以你想看看tenant.name、tenant.phone等中是否存在例如“Bob”?基本上如果它匹配任何属性?如果是这样,我相信这是标准功能,如果你只是通过过滤字符串。
    • 是的,没错,但我不想要任何,因为可能存在内部属性、不相关的属性等。这就是为什么我只是为此添加了自己的函数。
    • 感谢您的帮助,我真的不明白传递过滤器字符串会对属性执行不区分大小写的包含而不是相等,然后我可以执行例如这个“用户中的用户|过滤器:{名称:搜索,电话:搜索}”将其与多个属性进行匹配。我实际上最终得到了这个简单的解决方案,但接受的答案更能解决原始问题:)
    • 没问题,很高兴你把它整理好了:)。
    【解决方案3】:

    您需要测试这两个条件是否存在,如果两者都存在则返回值。像这样的:

    function contains(actual, expected) {
      if (actual.name.indexOf(expected) >= 0 && actual.phone.indexOf(expected) >= 0) {
        return actual;
      }
    }
    

    【讨论】:

    • 问题不在于我无法在函数内部测试两者,而是角度给了我对象中的属性,而不是对象本身......
    • 我纠正了解决方案中的一个错误。听起来您需要返回整个 actual 对象而不是单个属性。
    • 不幸的是,实际对象根本不存在。我希望实际是例如{ name: "1", phone "2"},而是在 contains 函数中立即得到 "1"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-21
    • 1970-01-01
    • 2017-10-08
    相关资源
    最近更新 更多