【问题标题】:Applying a angularjs filter after "Apply" button click单击“应用”按钮后应用 angularjs 过滤器
【发布时间】:2013-11-16 01:54:22
【问题描述】:

我有一个大数据列表(4000 多个项目)。开始输入时 - 我的浏览器冻结(最多 15 秒)。所以我需要关闭自动过滤功能,并将过滤功能绑定到按钮点击。 通过谷歌寻找答案没有结果。我该怎么做?请帮帮我:)

代码:

<input ng-model="search.phone" type="text" placeholder="Телефон...">
<input ng-model="search.name" type="text" placeholder="Имя...">
<input ng-model="search.city" type="text" placeholder="Город...">

<div ng-repeat="user in users | filter:search" class="user_block" ng-include src="userTemplate"></div>

和控制器:

app.controller("smsCtrl", ['$scope', 'smsData', 'createDialog', '$http', '$filter', function($scope, smsData, createDialog, $http, $filter){...}

【问题讨论】:

  • 你能发布你的代码吗?我过滤了大约 150k 个对象,花了我 4-6 秒。顺便说一句,你可以实现加载器
  • 你是什么意思“自动过滤”,你如何过滤你的项目
  • 还告诉我们您显示的每个项目有多少数据?如果每个数组项有许多数据绑定字段,则列表的呈现可能会导致性能问题。
  • @MaximShoustin 添加代码。
  • @jason 我的意思是在我开始在输入中输入内容后立即开始搜索。

标签: javascript angularjs filtering


【解决方案1】:

也许您可以尝试在其上添加一个去抖动并忘记按钮。

跟随link 到一个漂亮的去抖动代码以应用由 Lars Gersmann 创建的任何 DOM。您可以在文章末尾查看他的 JSFiddle 示例,了解其工作原理。

来自 GitHub 上 AngularJS 项目的 pull request #2129:

此外,ng-update-model-debounce 属性将允许在最后一次触发事件之后推迟实际的模型更新。此功能在单选按钮中不可用。

即ng-update-model-debounce="500" 持续 500 毫秒

以下是如何使用 debounce 的好方法

/**
 * uiDebounce service provides a mechanism for creating a wrapper around a function 
 * that ensures that the wrapped function is not called more frequently than a
 * given time interval.
 *
 * @param {!Function} func The function to be wrapped (debounced)
 * @param {number} wait How long between called to func
 * @param {Boolean} immediate If true then the function is invoked on the first call to the
 * wrapper function, otherwise the call will not happen until after the wait time has expired
 * @return {Function} A debounced wrapper around the func function.
 *
 * @example
 * function lookup(id) { ... lookup something ... }
 * var debounceLookup = debounce(lookup, 2000, false);
 * $scope.doLookup = function(msg) {
 *   var promise = debounceLookup(msg);
 *   console.log('called lookup: ', promise);
 *   promise.then(function(value) {
 *     console.log('lookup returned:', value);
 *   });
 * };
 */
angular.module('ui.services').factory('uiDebounce', function($timeout, $q) {
  return function(func, wait, immediate) {
    var timeout;
    var deferred = $q.defer();
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if(!immediate) {
          deferred.resolve(func.apply(context, args));
          deferred = $q.defer();
        }
      };
      var callNow = immediate && !timeout;
      if ( timeout ) {
        $timeout.cancel(timeout);
      }
      timeout = $timeout(later, wait);
      if (callNow) {
        deferred.resolve(func.apply(context,args));
        deferred = $q.defer();
      }
      return deferred.promise;
    };
  };
});

来源:Github - Angular-UI

【讨论】:

  • 链接可能会在一段时间后失效。如果发生这种情况,通常会从链接中复制至少一些有用的文本
  • @5uperdan 求建议。也许现在的答案更好地解释了我解决这个问题的方法。
【解决方案2】:

我找到了解决办法!

变化:

<div ng-repeat="user in users | filter:search" class="user_block" ng-include src="userTemplate"></div>

收件人:

<div ng-repeat="user in users" ng-hide="user.excludedByFilter" class="sms_user_block" ng-include src="userTemplate"></div>

为控制器添加“applySearchFilter”功能

    $scope.applySearchFilter = function() {
        var nameFilter = $scope.filters.name.toLowerCase();
        var phoneFilter = $scope.filters.phone;
        var cityFilter = $scope.filters.city;
        var showAll = 0 === nameFilter.length && 0 === phoneFilter.length && 0 === cityFilter.length;
        angular.forEach($scope.users, function(user) {
            if (showAll) {
                user.excludedByFilter = false;
            } else {
                user.excludedByFilter = (user.name.toLowerCase().indexOf(nameFilter) === -1) 
                                        || (user.phone.indexOf(phoneFilter) === -1) 
                                        || (user.city.indexOf(cityFilter) === -1);
            }
        });
    }

并为过滤按钮添加html代码:

<a class="btn btn-primary" href="#" ng-click="applySearchFilter()">Apply filters</a>

这行得通!

*注意,我在输入中将 ng-model="search.*" 重命名为 ng-model="filters.*"。

【讨论】:

    【解决方案3】:

    我在帮助一位同事时遇到了类似的事情(尽管在我们的案例中需要手动触发搜索过滤),并提出了一个类似但稍微简单一些的解决方案。

    使用你原来的重复 div。

    <div ng-repeat="user in users | filter:search">
        ...
    </div>
    

    创建一个对象来存储您的用户输入。

    $scope.search = {};
    $scope.userInput = {};
    

    将您的输入附加到此用户输入对象。

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

    创建一个循环用户输入对象的属性并将它们复制到您的搜索对象的函数。

    $scope.applySearch = function() {
        for(prop in $scope.userInput) {
            $scope.search[prop] = $scope.userInput[prop];
        }
    };
    

    最后,创建一个按钮来调用您的搜索功能。

    <button ng-click="applySearch()">Search</search>
    

    我希望这对某人有所帮助。

    【讨论】:

    • 这是非常聪明的方法。比公认的答案要好得多。喜欢!
    • 这是一个很好的解决方案,但您可以这样做:Object.assign($scope.search, $scope.userInput);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-30
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-26
    相关资源
    最近更新 更多