首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AngularJS筛选器不适用于来自2个不同键的多个单词

AngularJS筛选器不适用于来自2个不同键的多个单词
EN

Stack Overflow用户
提问于 2015-07-03 00:00:14
回答 2查看 1.4K关注 0票数 8

这是一些样例JSON数据。

代码语言:javascript
复制
$scope.Products = [
{
    "Variants": [],
    "SubCategoryID": "66",
    "ProductImagePath": "/images/britannia/887.png",
    "SubCategoryName": "Butter",
    "BrandName": "Britannia",
    "ProductID": "887",
    "BrandID": "76",
    "ProductName": "Butter"
},
{
    "Variants": [],
    "SubCategoryID": "71",
    "ProductImagePath": "/images/amul/886.png",
    "SubCategoryName": "Cheese",
    "BrandName": "Amul",
    "ProductID": "886",
    "BrandID": "47",
    "ProductName": "cheese"
},
{
    "Variants": [],
    "SubCategoryID": "106",
    "ProductImagePath": "/images/amul/885.png",
    "SubCategoryName": "Curd",
    "BrandName": "Amul",
    "ProductID": "885",
    "BrandID": "47",
    "ProductName": "curd"
}
]

这就是我渲染网页的方式。

代码语言:javascript
复制
<div ng-if="SearchText" class='box' ng-repeat="product in Products | filter:FilterExpr | orderBy:'ProductName'">
    <ng-include src="'commonTemplate.html'"></ng-include>
</div>

页面中有一个搜索文本框。当用户开始在serach文本框中键入内容时,我会将值赋给FilterExpr,如下所示。

代码语言:javascript
复制
$scope.$on('SearchTextChanged', function(event, SearchText) {

    if (SearchText.length >=3)  {
        $scope.FilterExpr = SearchText;
    }
});

当用户输入amul或奶酪或黄油时,它能够过滤产品。问题是,当用户输入amul curd或curd amul或butter are时,页面上没有显示任何产品。

如何让它工作?我需要做什么更改,以便它能够过滤多个单词。

EN

回答 2

Stack Overflow用户

发布于 2015-07-12 17:53:18

默认filter使用的默认comparator非常简单。它查找精确的搜索字符串,而不以任何方式解析搜索字符串。改进这一点的最简单方法是实现另一个comparator (doc)。

代码语言:javascript
复制
<div ng-if="SearchText" class='box' ng-repeat="product in Products | filter:FilterExpr:searchFuncComparator | orderBy:'ProductName'">
   <ng-include src="'commonTemplate.html'"></ng-include>
</div>

$scope添加comparator

代码语言:javascript
复制
$scope.searchFuncComparator = function(actual, expected) {
    // compare actual with expected and return true if match
    // otherwise false
};

剩下的就是实现上面你最喜欢的搜索方法了:)

票数 9
EN

Stack Overflow用户

发布于 2015-07-13 01:48:37

您可以使用自定义筛选器来执行此操作。要创建自定义筛选器,您需要在模块中注册一个新的筛选器工厂函数,并传入一个名称(我选择将其称为'multiFilter')。这个工厂函数返回一个filter函数,它将自动接收输入(比如来自ng-repeat的数组)作为它的第一个值。传递给filter函数的后续值是您将在筛选器标记中指定的值。

因此,为了使我们的过滤器更好和可重用,它将接受两个附加值。第一个是我们要搜索的对象键,第二个是搜索字符串。因此,在html中,您可以将此筛选器指定为| multiFilter: ['SubCategoryName', 'BrandName'] : SearchText

然后,您需要添加自定义过滤器:

代码语言:javascript
复制
.filter('multiFilter', function(){ //factory function
  return function(input, keys, query) { //filter function with input as first argument
    var results = [];
    var terms, key, value, x, i, j;

    if(angular.isDefined(keys) && angular.isDefined(query)) { //1.

      keys = angular.isArray(keys) ? keys : keys.split(' ');  //3.
      terms = query.toLowerCase().split(' ');  //4.

      for (x=0; x < input.length; x++) {  //5.
        for (i=0; i < keys.length; i++) {  //6.
          if (results.indexOf(input[x])===-1) {  //7.
            key = keys[i];
            for (j=0; j < terms.length; j++) {  //8.
              value = input[x][key].toString().toLowerCase();  //9.
              if (value.indexOf(terms[j])!==-1) {  //10.
                  results.push(input[x]);
              }
            }
          }
        }
      }
      return results; //11.

    } else {
      return input;  //2.
    }
  };
});

工作原理:

为了确保没有错误,如果搜索字符串或对象键为空,我们将检查它们是否都是用angular.isDefined().

  • If定义的,或者是未定义的,我们可以只返回过滤器接收到的数组。

  • 为了使筛选器更易于使用,我们将使其可以作为字符串传递对象键数组或单个键。如果它是一个字符串,我们将使用split。

  • 将其转换为一个包含一个元素的数组。接下来,因为您希望用户能够搜索多个术语并匹配任何搜索值,所以我们将搜索字符串拆分为一个数组。为了使我们的过滤器不区分大小写,我们将把搜索字符串(以及稍后要匹配的值)转换为lowercase.

  • In Javascript,本机for循环通常比其他数组迭代器更快,因此我们将使用三个嵌套的for循环。最外层的循环获取输入数组中的每个对象。

  • 下一个循环获取我们传递给筛选器的键数组中的每个键。

  • 此时,由于我们可能循环遍历同一对象的多个键,因此我们可以通过检查正在处理的对象是否已经在结果集中来提高过滤器的效率(这样我们就可以跳过内部循环,转到输入数组中的下一个对象)。

  • 最内层的循环循环遍历每个搜索项,并检查它们是否存在于当前输入数组属性值中。

  • ,为了使筛选器不区分大小写,我们将当前输入数组属性的值转换为字符串,然后转换为小写。

  • 如果找到搜索词,则将当前输入对象推送到结果数组。

  • 循环完成后,我们返回结果数组,以便在重复中使用或通过管道传输到下一个筛选器。

检查下面的代码片段以查看其操作:

代码语言:javascript
复制
var app = angular.module('filter.demo', []);

app.controller('ProductsController', ['$scope',
  function($scope) {

    $scope.FilterKeys = ['SubCategoryName', 'BrandName'];

    $scope.Products = [{
      "Variants": [],
      "SubCategoryID": "66",
      "ProductImagePath": "/images/britannia/887.png",
      "SubCategoryName": "Butter",
      "BrandName": "Britannia",
      "ProductID": "887",
      "BrandID": "76",
      "ProductName": "Butter"
    }, {
      "Variants": [],
      "SubCategoryID": "71",
      "ProductImagePath": "/images/amul/886.png",
      "SubCategoryName": "Cheese",
      "BrandName": "Amul",
      "ProductID": "886",
      "BrandID": "47",
      "ProductName": "cheese"
    }, {
      "Variants": [],
      "SubCategoryID": "106",
      "ProductImagePath": "/images/amul/885.png",
      "SubCategoryName": "Curd",
      "BrandName": "Amul",
      "ProductID": "885",
      "BrandID": "47",
      "ProductName": "curd"
    }];



  }
]);

app.filter('multiFilter', function() {
  return function(input, keys, query) {
    var results = [];
    var terms, key, value, x, i, j;

    if (angular.isDefined(keys) && angular.isDefined(query)) {

      keys = angular.isArray(keys) ? keys : keys.split(' ');
      terms = query.toLowerCase().split(' ');

      for (x = 0; x < input.length; x++) {
        for (i = 0; i < keys.length; i++) {
          if (results.indexOf(input[x]) === -1) {
            key = keys[i];
            for (j = 0; j < terms.length; j++) {
              value = input[x][key].toString().toLowerCase();
              if (value.indexOf(terms[j]) !== -1) {

                results.push(input[x]);
              }
            }
          }
        }
      }
      return results;

    } else {
      return input;
    }
  };
});
代码语言:javascript
复制
@import url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css');
代码语言:javascript
复制
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div  class="container">
  <h2>Demo</h2>
  <p><em>use search terms:</em> butter, cheese, amul, britannia, curd</p>
  
  <div ng-app="filter.demo" ng-controller="ProductsController">
    <label>Search:
      <input type="text" name="search" ng-model="SearchText" class="form-control" />
    </label>
    <div ng-if="SearchText" class='box' ng-repeat="product in Products | multiFilter: FilterKeys : SearchText | orderBy:'ProductName' track by $index">
      <h4 class="text-muted">{{product.SubCategoryName}}</h4>
      <p><strong>Brand Name:</strong> {{product.BrandName}}</p>
    </div>
  </div>
  
</div>

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31189400

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档