Angularjs 用户按enter键时的角度ui网格过滤器

Angularjs 用户按enter键时的角度ui网格过滤器,angularjs,angular-ui-grid,Angularjs,Angular Ui Grid,我已经实现了一个带有服务器端过滤、排序和分页的ui网格 我使用gridApi.core.on.filterChanged和$timeout一起检测过滤器更改,以等待用户完成键入。使用$timeout不是个坏主意,但我只想在enter键上过滤网格,但是filterChanged事件监视字段的值,我认为它无法访问keypress或keydown事件来检测enter键 如何在[code>enter键上调用ajax filter?filterChanged事件只告诉您它已更改,它不会过滤单个按键。最好的

我已经实现了一个带有服务器端过滤、排序和分页的ui网格

我使用gridApi.core.on.filterChanged和
$timeout
一起检测过滤器更改,以等待用户完成键入。使用
$timeout
不是个坏主意,但我只想在
enter
键上过滤网格,但是
filterChanged
事件监视字段的值,我认为它无法访问keypress或keydown事件来检测
enter


如何在[code>enter键上调用ajax filter?

filterChanged事件只告诉您它已更改,它不会过滤单个按键。最好的选择是使用新的自定义筛选器选项实现自定义筛选器模板,然后直接在您提供的筛选器指令上实现您的逻辑。请注意,您需要最新的不稳定版本,它将在RC21或3.0中发布,以先到者为准。

找到解决方案

如前所述,我正在搜索一个“干净”的解决方案,以避免向所有列添加
headerCellTemplate
,并更改大量代码

该解决方案以某种方式基于覆盖ui网格的
cellHeaderTemplate
,以使用我的自定义指令作为输入过滤器,而且效果非常好。我还可以向网格中添加不同类型的过滤器

angular
    .module('ui.grid')
    .run(['$templateCache', function ($templateCache) {

        // Override uiGridHeaderCell template to replace "input" field with "grid-filter" directive
        $templateCache.put('ui-grid/uiGridHeaderCell',
            "<div ng-class=\"{ 'sortable': sortable }\"><div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><span>{{ col.displayName CUSTOM_FILTERS }}</span><span ui-grid-visible=\"col.sort.direction\" ng-class=\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\">&nbsp;</span></div><div class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader  && col.colDef.enableColumnMenu !== false\" ng-click=\"toggleMenu($event)\" ng-class=\"{'ui-grid-column-menu-button-last-col': isLastCol}\"><i class=\"ui-grid-icon-angle-down\">&nbsp;</i></div><div ng-if=\"filterable\" class=\"ui-grid-filter-container\" ng-repeat=\"colFilter in col.filters\"><grid-filter type=\"{{colFilter.type}}\"></grid-filter><div class=\"ui-grid-filter-button\" ng-click=\"colFilter.term = null\"><i class=\"ui-grid-icon-cancel\" ng-show=\"!!colFilter.term\">&nbsp;</i><!-- use !! because angular interprets 'f' as false --></div></div></div>"
        );

        // Add custom templates to use in "grid-filter" directive
        $templateCache.put('ui-grid-filters/text',
            "<input type=\"text\" class=\"ui-grid-filter-input\" ng-model=\"colFilter.term\" ng-attr-placeholder=\"{{colFilter.placeholder || ''}}\">"
        );
        $templateCache.put('ui-grid-filters/dropdown',
            "<select class=\"ui-grid-filter-input\" ng-model=\"colFilter.term\" ng-options=\"option.text for option in colFilter.dropdownOptions \"><option value=''></option> </select>"
        );
        $templateCache.put('ui-grid-filters/date',
            "<input type='text' class=\"ui-grid-filter-input\" ng-model=\"colFilter.term\" mask=\"1399/99/99\" mask-options=\"{placeholder:' '}\" placeholder='{{colFilter.placeholder}}' />"
        );
    }])
    .directive('gridFilter', ['$templateCache', '$compile', function ($templateCache, $compile) {
        return {
            restrict: 'AE',
            replace: true,
            link: function (scope, elem, attrs) {
                var type = attrs['type'] || 'text';
                var grid = scope.$parent.$parent.grid;

                var filter = function () {
                    // Filtering comes here. We have full access to grid and it's filter terms here.
                };

                var template = $compile($templateCache.get('ui-grid-filters/' + type))(scope);
                elem.replaceWith(template);
                elem = template;

                elem.keypress(function (e) {
                    if (e.which == 13) {
                        filter();
                    }
                });

                if (type == 'dropdown') {
                    elem.change(function (e) {
                        filter();
                    })
                }

                // Handle clear button click action
                scope.$watch('$parent.colFilter.term', function (newVal, oldVal) {
                    if (newVal === null && oldVal !== null) {
                        filter();
                    }
                });
            }
        }
    }]
);

使用模式的watch过滤ui网格调用的事件,但watch方法调用keypress,因此我们可以通过添加指令将keypress事件更改为文本框的blur事件

directive('ngModelOnblur', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elm, attr, ngModelCtrl) {
            elm.unbind('input').unbind('keydown').unbind('blur');
            elm.bind('change', function () {
                scope.$apply(function () {
                    ngModelCtrl.$setViewValue(elm.val());
                });
            });
        }
    };
});

uigrid
textbox
中添加指令,并且仅在
textbox
的更改事件中调用ui grid filter.api或输入键。

我不确定您为什么需要自己处理输入键,但存在gridApi.edit.on.afterCellEdit事件。但是gridApi.rowEdit.on.saveRow应该能够手动触发保存。@您:我想自己处理
enter
,因为ui grid
filterChanged
事件是使用
$watch
实现的,所以当用户按enter键时,我无法调用ajax filter。而且我不想保存任何更改。只是ajax过滤。我明白了。我不确定ui网格是否内置了此功能,但我相信使用带有ng键的自定义
cellTemplate
可以实现此功能。@您:是的,这是一个解决方案,但我不想将
headerCellTemplate
添加到所有列中。我想找到一个“更干净”的解决方案。如果我找不到更好的解决方案,我会这样做。有人能举一个“使用ng键的cellTemplate可以实现这一点”的例子吗?有时它很有用。一旦你访问了网格对象,我就不知道如何使用它进行过滤了?@Dallin:很抱歉回答得太晚了。您可以使用所有网格选项来过滤数据。例如,可以使用
grid.options.filter
grid.options.paginationCurrentPage
等。
directive('ngModelOnblur', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elm, attr, ngModelCtrl) {
            elm.unbind('input').unbind('keydown').unbind('blur');
            elm.bind('change', function () {
                scope.$apply(function () {
                    ngModelCtrl.$setViewValue(elm.val());
                });
            });
        }
    };
});