【问题标题】:Angular Filters: How to pre-filter so angular filters consider only a partial of the whole data object角度过滤器:如何进行预过滤,以便角度过滤器仅考虑整个数据对象的一部分
【发布时间】:2015-05-30 04:20:00
【问题描述】:

我有一个包含多个列的大型数据表(从 json api 获取数据),并希望实现多个过滤器,执行以下操作:

  1. 用于选择应考虑哪个数据列的选项(包含 thead 选项的下拉菜单)[my columnFilter] 然后
  2. 用于过滤特定数据部分的输入字段 [my searchFilter]

我已经让 searchFilter 工作了,但我不确定如何连接 columnFilter 并使 searchFilter 仅适用于选定的数据部分。

假设我只想看到包含世界“蓝色”的描述。

如何绑定这两个过滤器并使其工作?

这是我的一些代码:

  Select data column:
  <select ng-model="columnFilter" ng-options="heading for heading in headings">
  </select>
</div>
<div class="col-sm-12">
   Filter selection: <input type='text' ng-model="searchFilter" />
</div>
<table class="table table-bordered">
    <thead>
      <tr>
        <th>URL</th>
        <th>Title</th>
        <th>Traffic</th>
        <th>Description</th>
        <th>ID</th>
      </tr>
  </thead>
  <tbody ng-repeat="url in urls | filter:searchFilter">
    <tr>
      <td>{{url.url}}</td>
      <td>{{url.title}}</td>
      <td>{{url.traffic}}</td>
      <td>{{url.descr}}</td>
      <td>{{url.id}}</td>
    </tr>
    </tbody>
</table>

以及一个工作插件的链接:http://plnkr.co/edit/TddllGiey0RmCx18eVdd?p=preview

【问题讨论】:

    标签: javascript angularjs angularjs-ng-repeat ng-options angular-filters


    【解决方案1】:

    据我所知,有两种主要方法可以解决您的问题。

    1. 定义自定义过滤器
    2. 定义一个函数来过滤数据并使用 ng-show 或 ng-hide 调用它

    我有一个大数据表

    如果我理解得很好,您指定这是因为性能是一个大问题。

    有一篇很好的文章揭示了这两种解决方案之间的区别:http://www.bennadel.com/blog/2487-filter-vs-nghide-with-ngrepeat-in-angularjs.htm

    由于性能对你来说可能真的很重要,我建议你使用第二种方法。

    在你看来:

    <tbody ng-repeat="url in urls" ng-show="filterUrl(url)">
    

    在您的控制器中:

    $scope.searchFilter = "";
    $scope.columnFilter = $scope.headings[5];
    
    $scope.filterUrl = function(url){ 
      if(!$scope.searchFilter || $scope.searchFilter == "")
        return url;
      var searchFilter= $scope.searchFilter.toLowerCase();
      var trafficString = url.traffic.toString();
      var idString = url.traffic.toString();
      switch($scope.columnFilter){
        case $scope.headings[0]:
          return url.title.toLowerCase().indexOf(searchFilter) != -1;
        case $scope.headings[1]:
          return url.url.toLowerCase().indexOf(searchFilter) != -1;
        case $scope.headings[2]:
          return trafficString.indexOf(searchFilter) != -1;
        case $scope.headings[3]:
          return url.descr.toLowerCase().indexOf(searchFilter) != -1;
        case $scope.headings[4]:
          return idString.indexOf(searchFilter) != -1;
        case $scope.headings[5]: 
          return url.title.toLowerCase().indexOf(searchFilter) != -1 ||
          url.url.toLowerCase().indexOf(searchFilter) != -1 ||
          trafficString.indexOf(searchFilter) != -1 ||
          url.descr.toLowerCase().indexOf(searchFilter) != -1 ||
          idString.indexOf(searchFilter) != -1;
      }
    };
    

    更新: 如果您选择第一种方法:

    在你看来:

     <tbody ng-repeat="url in urls | filterByColumn: searchFilter :columnFilter">
    

    过滤器:

    app.filter('filterByColumn', function(){
      return function(urls, text, columnFilter){
        var processed = [];
         if(!text || text == "")
            return urls;
        urls.forEach(function(url){
          var searchFilter= text.toLowerCase();
          var trafficString = url.traffic.toString();
          var idString = url.traffic.toString();
          switch(columnFilter){
            case "Title":
              if( url.title.toLowerCase().indexOf(searchFilter) != -1)
                processed.push(url);
              break;
            case "Url":
              if(url.url.toLowerCase().indexOf(searchFilter) != -1)
                processed.push(url);
              break;
            case "Traffic":
              if(trafficString.indexOf(searchFilter) != -1)
                processed.push(url);
              break;
            case "Description":
              if(url.descr.toLowerCase().indexOf(searchFilter) != -1)
                processed.push(url);
              break;
            case "Id":
              if( idString.indexOf(searchFilter) != -1)
                processed.push(url);
              break;
            case "All": 
              if( url.title.toLowerCase().indexOf(searchFilter) != -1 ||
              url.url.toLowerCase().indexOf(searchFilter) != -1 ||
              trafficString.indexOf(searchFilter) != -1 ||
              url.descr.toLowerCase().indexOf(searchFilter) != -1 ||
              idString.indexOf(searchFilter) != -1)
                processed.push(url);
              break;
          }
        });
        return processed;
      };
    });
    

    这是一个小插曲:http://plnkr.co/edit/xCwI2AURFpvb6xHgYHxS?p=preview

    【讨论】:

    • 太棒了,它完全按照我想要的方式工作,而且这篇文章也很有帮助。还有一个问题 - 结合这两个过滤器只是我最终想要构建的第一步:4 个链接在一起的过滤器(类似于谷歌分析使用的过滤器:awesomescreenshot.com/06b4q53x83 filter1: include/exclude filter2: select column (在这里解决)过滤器3:不同的过滤器选项(包括,开头,等于等)过滤器4:输入字段(在这里解决)你仍然建议定义函数还是更好地使用自定义过滤器?
    • 你能给我一个大概显示的行数吗? 100 ? 500? 1000?更多?
    • 确定 - 700 - 1000 之间
    • 您会在其他页面上重复使用这些过滤器吗? (分开或组合)如果回答是肯定的,那么我建议您使用过滤器。
    • 非常感谢您的帮助 - 希望我能再次对此表示赞同。检查了plunker,但最新版本(25)似乎不起作用(数据表几乎是空的)
    【解决方案2】:

    我建议你编写这样的简单自定义过滤器。

    .filter('myfilter', function(){
      return function(input, column, text){
        if (!input || !column || !text) return input;
        return input.filter(function(item){
          var value = item[column.toLowerCase()];
          if (!value)return false;
          return value.indexOf(text)>-1;
        });
      };
    });
    

    您可以在 html 中使用此过滤器。

    ng-repeat="url in urls | myfilter:columnFilter:searchFilter"
    

    This is plunker.

    【讨论】:

    • 谢谢 - 我试过你的 plunker,但 searchFilter 不起作用 - 知道如何解决这个问题吗?
    • 为了让sample尽可能简单,我使用Array.filter来实现过滤功能。如果您使用不支持 Array.filter 的旧浏览器,则此示例无法正常工作。我的 chrome(和 Firefox)可以正常工作。当然你需要稍作改动以支持旧浏览器。
    • 顺便说一句,这是the new version of sample,它使用 underscore.js 来支持旧浏览器。我的 IE9 运行良好。
    【解决方案3】:

    直接从创建自定义过滤器的角度页面查看此示例。 https://docs.angularjs.org/guide/filter

    您可以在此处看到,您可以创建一个接受 2 个输入、实际对象和一个参数的过滤器。通过将列名作为参数传递,您可以缩小对正确行的搜索范围。

    【讨论】:

    • 感谢您 - 我是 angular 新手,不知道如何将示例转移到我的案例中。你能指出我正确的方向吗?
    猜你喜欢
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    相关资源
    最近更新 更多