角度ui-grid / ng-grid filter更换频繁

时间:2014-12-04 18:50:30

标签: angularjs ng-grid angular-ui-grid

我尝试使用服务器端排序,服务器端分页和服务器端过滤来实现角度网格。使用ui-grid(不稳定),我添加了ui.grid.paging并使所有内容都运行起来。非常好,对开发人员赞不绝口。

然而.... $ scope.gridApi.core.on.filterChanged正在按下每个按键,所以当我搜索" Patrick"在givenname列中,触发了七个事件,七个get-requests命中了我的服务器。更糟糕的是,由于它是一个很大的过滤器,这个操作非常昂贵,结果我甚至相互超越,就像最特殊的过滤器获得最快的结果一样,在处理不太具体的结果之前触发成功。

我想放慢速度,就像在进入停止后开火一样#34;。我对javascript和REST非常陌生,这是我的第一个真实世界项目。我真的很感激如何处理这个问题的任何想法。这感觉就像一个常见的场景,因此可能会有一些我缺少的标准解决方案或最佳实践。

此致, 帕特里克。

4 个答案:

答案 0 :(得分:16)

如果你想去"所有角度"我建议在$timeout事件处理程序中使用on.filterChanged

if (angular.isDefined($scope.filterTimeout)) {
    $timeout.cancel($scope.filterTimeout);
}
$scope.filterTimeout = $timeout(function () {
    getPage();
}, 500);

其中500是你想要在每个on.filterChanged事件之前等待到服务器之前的时间(以毫秒为单位),而getPage()是实际进入服务器并检索数据的函数。

请勿忘记取消控制器上的$timeout'销毁'事件:

$scope.$on("$destroy", function (event) {
    if (angular.isDefined($scope.filterTimeout)) {
        $timeout.cancel($scope.filterTimeout);
    }
});

答案 1 :(得分:9)

我正在处理同样的问题,我提出了另一个解决方案,恕我直言更多" Angular-friendly"。我使用了Angular 1.3中引入的ngModelOptions directive。 我用自定义的模板替换了uiGrid的默认过滤器模板(" ui-grid / ui-grid-filter"),并在输入上配置了ngModelOptions指令,默认去抖值为300 ms,模糊0毫秒。

这是一个基于ui-grid 3.0.5原始模板的示例模板,其中我还通过Bootstrap类更改了默认的CSS类:

$templateCache.put('ui-grid/ui-grid-filter-custom',
  "<div class=\"ui-grid-filter-container\" ng-repeat=\"colFilter in col.filters\" ng-class=\"{'ui-grid-filter-cancel-button-hidden' : colFilter.disableCancelFilterButton === true }\">" +
  "<div ng-if=\"colFilter.type !== 'select'\"><input type=\"text\" class=\"input-sm form-control\" ng-model=\"colFilter.term\" ng-model-options=\"{ debounce : { 'default' : 300, 'blur' : 0 }}\" ng-attr-placeholder=\"{{colFilter.placeholder || ''}}\" aria-label=\"{{colFilter.ariaLabel || aria.defaultFilterLabel}}\"><div role=\"button\" class=\"ui-grid-filter-button\" ng-click=\"removeFilter(colFilter, $index)\" ng-if=\"!colFilter.disableCancelFilterButton\" ng-disabled=\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\" ng-show=\"colFilter.term !== undefined && colFilter.term !== null && colFilter.term !== ''\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"aria.removeFilter\">&nbsp;</i></div></div>" +
  "<div ng-if=\"colFilter.type === 'select'\"><select class=\"form-control input-sm\" ng-model=\"colFilter.term\" ng-attr-placeholder=\"{{colFilter.placeholder || aria.defaultFilterLabel}}\" aria-label=\"{{colFilter.ariaLabel || ''}}\" ng-options=\"option.value as option.label for option in colFilter.selectOptions\"><option value=\"\"></option></select><div role=\"button\" class=\"ui-grid-filter-button-select\" ng-click=\"removeFilter(colFilter, $index)\" ng-if=\"!colFilter.disableCancelFilterButton\" ng-disabled=\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\" ng-show=\"colFilter.term !== undefined && colFilter.term != null\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"aria.removeFilter\">&nbsp;</i></div></div>" +
  "</div>"
);

此操作的最后一步是在您启用过滤的每个columnDef中设置此模板:

columnDefs: [{
  name: 'theName',
  displayName: 'Whatever',
  filterHeaderTemplate: 'ui-grid/ui-grid-filter-custom'
}]

不幸的是,我找不到任何方法来全局定义这个模板,所以我不得不在任何地方重复filterHeaderTemplate ......这是唯一的缺点,但另一方面,你也可以添加如果需要,可以为自定义模板添加更多过滤器。

希望它有所帮助!

答案 2 :(得分:1)

我建议你看一下reactive-extensions for Javascript。 Reactive专为这些场景而构建。有一个名为.Throttle(毫秒)的方法,你可以将它附加到一个observable,它将在x毫秒过去之后调用一个处理程序(命中你的API),以便用户不输入任何内容。

Rx-Js and angular play well together

以下是我的一个类似项目的例子:

observeOnScope($scope, 'tag', true)
            .throttle(1000)
            .subscribe(function (data) {
                if (data.newValue) {
                    $http({
                        url: api.endpoint + 'tag/find',
                        method: 'GET',
                        params: {text: data.newValue}
                    }).then(function (result) {
                        $scope.candidateTags = result.data;
                    })
                }
            });

此代码采用$scope.tag并将其转换为可观察对象。 .throttle(1000)表示在$scope.tag 1秒后不更改订阅功能将被调用,其中(data)是新值。之后,您可以点击您的API。

我用它来从我的API做一个值的类型查找,所以每当一个字母发生变化时点击后端显然不是这样的方法:)

答案 3 :(得分:0)

JavaScript setTimeout 函数也可用于提供延迟,如下所示。

$scope.gridApi.core.on.filterChanged( $scope, function() {

    if (angular.isDefined($scope.filterTimeout)) {
        clearTimeout($scope.filterTimeout);
    }
    $scope.filterTimeout = setTimeout(function(){
        getPage();
    },1000);

});