angular ui-grid filter when user presses enter key

余生长醉 提交于 2019-12-10 19:26:39

问题


I have implemented a ui-grid with server side filtering, sorting and pagination.

I use gridApi.core.on.filterChanged to detect filter change alongside $timeout to wait for user to finish typing. It's not bad idea to use $timeout, but I want to filter grid only on enter key, but filterChanged event watches the value of field and I think it doesn't have access to keypress nor keydown events to detect enter key.

How can I call ajax filter on enter key?


回答1:


Solution found!

As I told before, I was searching for a "CLEAN" solution to avoid adding headerCellTemplate to all columns and changing lots of my code.

This solution is somehow based on overriding ui-grid's cellHeaderTemplate to use my custom directive as input filter, and it works great. I can also add different types of filters to my grid.

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();
                    }
                });
            }
        }
    }]
);

And here is a sample gridOptions object.

$scope.gridOptions = {
    enableFiltering: true,
    enableRowSelection: true,
    enableGridMenu: true,
    paginationPageSizes: [25, 50, 75],
    paginationPageSize: 25,

    useExternalSorting: true, // Sorting is handled using gridApi.core.on.sortChanged() event
    useExternalFiltering: true, // Filtering is handled in custom directive
    useExternalPagination: true, // Pagination is handled using gridApi.pagination.on.paginationChanged() event

    columnDefs: [
        {
            field: 'username',
            displayName: "Username"
        },
        {
            field: 'status',
            displayName: 'Status',
            cellTemplate: '<div class="text-center">' +
            '<span ng-show="row.entity.status==1">Enabled</span>' +
            '<span ng-show="row.entity.status==2">Disabled</span>' +
            '</div>',
            filter: {
                type: 'dropdown',
                dropdownOptions: [
                    {
                        id: 1,
                        text: 'Enabled'
                    },
                    {
                        id: 2,
                        text: 'Disabled'
                    }
                ]
            }
        },
        {
            field: 'birthDate',
            displayName: 'Birth Date',
            filters: [
                {
                    type: 'date',
                    placeholder: 'From'
                },
                {
                    type: 'date',
                    placeholder: 'To'
                }
            ]
        },
    ]
}



回答2:


The filterChanged event only tells you that it's changed, it doesn't filter individual key presses. The best option would be to implement a custom filter template using the new custom filter options: http://ui-grid.info/docs/#/tutorial/306_custom_filters, and then implement your logic directly on the filter directive that you provide. Note that you'll need the latest unstable for this - it will release in RC21 or 3.0, whichever comes first.




回答3:


Filter event of ui grid calls with watch of the modal,but watch method calls on keypress so we can change the keypress event to blur event of text box by adding the directive

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());
                });
            });
        }
    };
});

add the directive in textbox of uigrid and ui grid filter.api called only on change event of textbox or enter key.



来源:https://stackoverflow.com/questions/29726521/angular-ui-grid-filter-when-user-presses-enter-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!