搜索过滤器不适用于具有通用模型的多个字段

时间:2016-08-19 21:43:32

标签: javascript angularjs angularjs-filter angular-ngmodel

我正在尝试创建一个搜索框,可以单独过滤搜索对象的各种属性 在我目前的解决方案中,我必须创建一个模拟内置搜索的自定义搜索功能:

<!DOCTYPE html>
<html ng-app="m1">
  <head>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js'></script>
  </head>
  <body ng-controller="c1">
    <div>
      Filter
      <select ng-model="filterKey">
        <option value="bookId">By Id</option>
        <option value="bookTitle">By Title</option>
        <option value="author">By Author</option>
        <option value="cost">By Cost</option>
      </select>
      <input type="text" ng-model="filterValue">
    </div>
    <table>
      <tr>
        <th>SI. No.</th>
        <th>Details</th>
      </tr>
      <tr custom-tr ng-repeat="book in books | filter: bookFilter(filterKey, filterValue)">
        <td>{{ $index + 1 }}</td>
        <td>
          <table>
            <tr>
              <td>Book ID:</td>
              <td>{{book.bookId}}</td>
            </tr>
            <tr>
              <td>Book Title:</td>
              <td>{{book.bookTitle}}</td>
            </tr>
            <tr>
              <td>Book Author:</td>
              <td>{{book.author}}</td>
            </tr>
            <tr>
              <td>Book Cost:</td>
              <td>{{book.cost}}</td>
            </tr>
          </table>
        </td>
      </tr>
    </table>
  </body>
  <script type="text/javascript">
    var m1 = angular.module("m1", []);

    m1.controller('c1',function($scope)
    {
      $scope.books = [
      {
          "bookId": 101,
          "bookTitle": "Angular JS",
          "author": "Green",
          "cost":375,
      },
      {
          "bookId": 102,
          "bookTitle": "Instant AngularJS Starter",
          "author": "Dan Menard",
          "cost":150,
      },
      {
          "bookId": 103,
          "bookTitle": "Ng-Book: The Complete Book on AngularJS",
          "author": "Ari Lerner",
          "cost":4657,
      }];

      $scope.bookFilter = function(filterKey, filterValue)
      {
        return function(book)
        {
          if(!filterKey || !filterValue)
          {
            return true;
          }
          // Emulating the built-in search algorithm
          return String(book[filterKey]).toLowerCase().includes(filterValue.toLowerCase());
        };
      };
    });
  </script>
</html>

我想在不手动编写搜索算法的情况下做同样的事情(并且无需同时编写更多代码)。

我目前的尝试是:

<!DOCTYPE html>
<html ng-app="m1">
  <head>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js'></script>
  </head>
  <body ng-controller="c1">
    <div>
      Filter
      <select ng-model="filterKey">
        <option value="bookId">By Id</option>
        <option value="bookTitle">By Title</option>
        <option value="author">By Author</option>
        <option value="cost">By Cost</option>
      </select>
      <input type="text" ng-model="filterValue">
    </div>
    <table>
      <tr>
        <th>SI. No.</th>
        <th>Details</th>
      </tr>
      <tr custom-tr ng-repeat="book in books | filter: {filterKey: filterValue}">
        <td>{{ $index + 1 }}</td>
        <td>
          <table>
            <tr>
              <td>Book ID:</td>
              <td>{{book.bookId}}</td>
            </tr>
            <tr>
              <td>Book Title:</td>
              <td>{{book.bookTitle}}</td>
            </tr>
            <tr>
              <td>Book Author:</td>
              <td>{{book.author}}</td>
            </tr>
            <tr>
              <td>Book Cost:</td>
              <td>{{book.cost}}</td>
            </tr>
          </table>
        </td>
      </tr>
    </table>
  </body>
  <script type="text/javascript">
    var m1 = angular.module("m1", []);

    m1.controller('c1',function($scope)
    {
      $scope.books = [
      {
          "bookId": 101,
          "bookTitle": "Angular JS",
          "author": "Green",
          "cost":375,
      },
      {
          "bookId": 102,
          "bookTitle": "Instant AngularJS Starter",
          "author": "Dan Menard",
          "cost":150,
      },
      {
          "bookId": 103,
          "bookTitle": "Ng-Book: The Complete Book on AngularJS",
          "author": "Ari Lerner",
          "cost":4657,
      }];
    });
  </script>
</html>

但这不起作用,可能是因为行filterKey中没有正确读取<tr custom-tr ng-repeat="book in books | filter: {filterKey: filterValue}">

我怀疑是因为如果我手动编写密钥,它可以工作:

<tr custom-tr ng-repeat="book in books | filter: {'author': filterValue}">

但是,这样我就必须为对象中存在的每个键编写过滤器表达式(如果有20个键,我们该怎么做?!!)。

所以,我的问题是如何实现搜索功能:

  • 我自己不试图模仿搜索算法。
  • 无需单独为每个密钥编写过滤器表达式

修改
我只是尝试了多个字段:

<tr custom-tr ng-repeat="book in books | filter: {'author': filterValue} | filter: {'cost': filterValue}">

它根本不起作用。
那么,无论如何,这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

你在找这样的东西吗?

  $scope.getFilteredBooks = function() {
    var filter = {};
    filter[$scope.filterKey] = $scope.filterValue;
    return filterFilter($scope.books, filter);
  };

Plunker