【问题标题】:filter multiple fields using single input in AngularJS在 AngularJS 中使用单个输入过滤多个字段
【发布时间】:2014-01-25 11:51:33
【问题描述】:

我有一个如下的 JSON 对象

[{
    "id": 1,
    "firstName": "Jennifer",
    "middleName": null,
    "lastName": "Aniston",
    "address": "New York City",
}, {
    "id": 2,
    "firstName": "Angelina",
    "middleName": null,
    "lastName": "Jolie",
    "address": "Beverley Hills",
}, {
    "id": 3,
    "firstName": "Emma",
    "middleName": null,
    "lastName": "Watson",
    "address": "London",
}]

我正在使用 ng-repeat 在视图中填充这些数据。

<td ng-repeat="row in list | filter:filterBeauties">
{{row.firstName}} {{row.lastName}}
</td>

现在我有一个输入框,我想用它来过滤这些名称。我想使用相同的输入框过滤 firstName 然后过滤 lastName 并且不过滤其他任何内容(例如地址)。

<input type="text" placeholder="Filter" ng-model="filterBeauties.firstName">

知道如何实现吗?

【问题讨论】:

  • (firstName 和 lastName) 或者您想要(firstName 或 lastName)
  • 名字和姓氏。因此,如果我在输入框中输入 Jennifer Aniston,它必须过滤为 Jennifer Aniston。
  • 好的,我认为这只能通过编写自定义过滤器来完成 - 因为您需要解析输入查询参数...
  • 我了解您想要做什么,但从架构的角度来看,我建议您将 firstAndLastName 放在您的视图中,并将您的搜索模型放在上面。
  • @ChrisStory 你的意思是我应该改变后端?

标签: angularjs angularjs-filter


【解决方案1】:

试试这个fiddle

本质上,我创建了一个子结构,用于在显示的数据结构中进行过滤,并仅对该属性进行过滤(例如“filterTerms”):

HTML:

<div ng-controller="MyCtrl">
   <input type="text" ng-model="search.filterTerms">
   <table border="1">
      <tr ng-repeat="row in list | filter:search">
         <td>{{row.firstName}} {{row.lastName}}</td>
      </tr>
   </table>
</div>

JavaScript:

var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.list = [{
    "id": 1,
    "address": "New York City",
    "firstName": "Jennifer",
    "middleName": null,
    "lastName": "Aniston",
    "filterTerms": {
        "firstName": "Jennifer",
        "middleName": null,
        "lastName": "Aniston",
    }
}, {
    "id": 1,
    "address": "New York City",
    "firstName": "Jennifer",
    "middleName": null,
    "lastName": "Leela",
    "filterTerms": {
        "firstName": "Jennifer",
        "middleName": null,
        "lastName": "Leela",            
    }
}, {
    "id": 2,
    "address": "Beverley Hills",
    "firstName": "Angelina",
    "middleName": null,
    "lastName": "Jolie",
    "filterTerms": {
        "firstName": "Angelina",
        "middleName": null,
        "lastName": "Jolie",            
    }
}, {
    "id": 3,
    "address": "London",
    "firstName": "Emma",
    "middleName": null,
    "lastName": "Watson",
    "filterTerms": {
        "firstName": "Emma",
        "middleName": null,
        "lastName": "Watson",            
    }
}];
}

对于这种情况,您可以通过将所有名称放在一个字段中来进一步简化这一点(参见小提琴here

HTML:

<div ng-controller="MyCtrl">
    <input type="text" ng-model="search.filterTerm" />
    <table border="1">
        <tr ng-repeat="row in list | filter:search">
            <td>{{row.first}} {{row.last}} {{row.address}}</td>
        </tr>
    </table>
</div>

JavaScript:

var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
    $scope.list = [{
        "id": 0, "first": "Jenny", "last": "Sorenson", "address": "123 W. Wallnut St.",
        "filterTerm": "Jenny Sorenson"
    },{
        "id": 0, "first": "Susan", "last": "Hinkle", "address": "456 W. Doorbell Dr.",
        "filterTerm": "Susan Hinkle"
    },{
        "id": 0, "first": "Rachel", "last": "Karlyle", "address": "789 W. Sunset Blvd.",
        "filterTerm": "Rachel Karlyle"
    },{
        "id": 0, "first": "Gwen", "last": "Lippi", "address": "0 W. Silly Cir.",
        "filterTerm": "Gwen Lippi"
    }]
}

【讨论】:

  • 这就像为列表创建一个index。好主意。谢谢。
【解决方案2】:

考虑到您的用户有这种形式:

{
  "id": 2,
  "firstName": "Angelina",
  "middleName": null,
  "lastName": "Jolie",
  "address": "Beverley Hills"
}

如果您想同时按他的名字、姓氏或两者同时搜索某个用户,则需要将它们连接在一起。

$scope.query = '';

$scope.search = function (user) {
  var query = $scope.query.toLowerCase(),
  fullname = user.firstName.toLowerCase() + ' ' + user.lastName.toLowerCase();

  if (fullname.indexOf(query) != -1) {
    return true;
  }
  return false;
};

如果当前用户满足您的查询,此函数将返回true,否则返回false。在函数内部,我建议将您的查询放在小写字母中,这样您就不必处理用户将在搜索输入中输入的大写字母。

这是 HTML:

<input type="text" placeholder="Search" ng-model="query">
<table>
   <tr ng-repeat="user in users | filter:search">
      <td>{{user.firstName}} {{user.lastName}}</td>
   </tr>
</table>

只有在您尝试搜索 Angelina JolieAngelinaJolie 甚至 InA JOLIe 时,此技术才有效(毕竟为什么不呢)。如果您尝试先搜索姓氏,例如Jolie Angelina,它将无法正常工作。您可以通过在函数中创建第二个全名(例如 reverseFullname)轻松修复它,首先连接 lastName,然后连接 firstName,并像第一个全名字符串一样对其进行测试。

【讨论】:

【解决方案3】:

好的,这就是我为解决它所做的。

我在 json 对象中添加了一个新项目(使用angular.forEach 函数)并被它过滤。

$scope.list = beauties.query(function(response) {
    angular.forEach(response, function(value, key) {
          var fullName = value.firstName + ' ' + value.lastName;
          $scope.list[key].fullName = fullName;
   });
});

输入框代码:

<input type="text" placeholder="Filter" ng-model="filterBeauties.fullName">

ng-重复

<td ng-repeat="row in list | filter:filterBeauties">
{{row.firstName}} {{row.lastName}}
</td>

【讨论】:

    【解决方案4】:

    您可以将第三个参数传递给过滤函数:

    $filter('filter')(list, {'firstName':search});
    

    我会做如下的事情:

    <input type="text" ng-model="search">
    <table border="1">
        <tr ng-repeat="row in list | filterBoth:search">
            <td>{{row.firstName}} {{row.lastName}}</td>
        </tr>
    </table>
    

    然后将自定义过滤器写成:

    myApp.filter('filterBoth', function($filter) {
      return function(list, search) {
        if (!search) return list;
    
        var arrSearch = search.split(' '),
            lookup = '',
            result = [];
    
        arrSearch.forEach(function(item) {
          lookup = $filter('filter')(list, {'firstName': item});console.log(lookup);
          if (lookup.length > 0) result = result.concat(lookup);
        });
    
        return result;
      };
    });
    

    演示:http://jsfiddle.net/wAp4S/1/

    唯一的问题是你会得到重复的行,因为你正在连接两个相似的数组,可以使用_.uniqunderscore.js 方法轻松修复。

    【讨论】:

    • 嗨,你分享的 jsFiddle 并没有真正按照我想要的方式工作。如果您在输入框中输入“Jennifer Aniston”,它不会返回任何结果。
    • 哦。在这种情况下,您必须按空格分割搜索,分别过滤每个单词,对结果进行分组,使其唯一,最后更新范围。当前的演示足以让您继续按照您的期望进行探索。
    • 这不起作用。检查你的jsfiddle。如果我输入Ang 我只能看到Angelina 而不是Aniston
    • 我认为 'Ang' 不应该匹配 'Aniston'。但是,“An”也不会返回“Aniston”。似乎姓氏没有在小提琴中被过滤。
    • 这并没有真正发挥应有的作用。它还会过滤地址,即使这不是想要的行为。
    【解决方案5】:

    尝试使用angular-filter 库,而不是编写复杂的过滤器searchField 过滤器在这里会很有帮助。

    https://github.com/a8m/angular-filter

    控制器

    $scope.users = [
      { first_name: 'Sharon', last_name: 'Melendez' },
      { first_name: 'Edmundo', last_name: 'Hepler' },
      { first_name: 'Marsha', last_name: 'Letourneau' }
    ];
    

    HTML

    <input ng-model="search" placeholder="search by full name"/>
    <th ng-repeat="user in users | searchField: 'first_name': 'last_name' | filter: search">
      {{ user.first_name }} {{ user.last_name }}
    </th>
    <!-- so now you can search by full name -->
    

    祝你好运。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      • 2017-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多