Najafsen
Najafsen

Reputation: 343

angular ui-grid filter when user presses enter key

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?

Upvotes: 4

Views: 9596

Answers (3)

testuigrid
testuigrid

Reputation: 1

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.

Upvotes: 0

Najafsen
Najafsen

Reputation: 343

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'
                }
            ]
        },
    ]
}

Upvotes: 2

PaulL
PaulL

Reputation: 6650

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.

Upvotes: 1

Related Questions