4

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?

5
  • I am not sure why you need to handle enter key yourself, but there is gridApi.edit.on.afterCellEdit event. but gridApi.rowEdit.on.saveRow should able to trigger saving manually. Commented Apr 19, 2015 at 6:37
  • @YOU: I want to handle enter myself, because ui-grid filterChanged event is implemented using $watch, so I cannot call ajax filter when user presses enter key. And also I don't want to save any changes. Just ajax filtering. Commented Apr 19, 2015 at 7:18
  • i see. I am not sure ui-grid have this function built-in, but I believe using custom cellTemplate with ng-keydown on it could achieve that. Commented Apr 19, 2015 at 8:13
  • @YOU: Yes, this is a solution, but I don't want to add headerCellTemplate to all columns. I want to find a "CLEANER" solution. If I fail to find better solution, I would do this way. Commented Apr 19, 2015 at 8:26
  • can somebody make a example of "cellTemplate with ng-keydown on it could achieve that"? it's useful sometime. Commented Sep 17, 2015 at 19:02

3 Answers 3

2

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'
                }
            ]
        },
    ]
}
Sign up to request clarification or add additional context in comments.

2 Comments

Once you have access to the grid object, I'm unclear how to use it to filter?
@Dallin: Sorry to answer late. You can use all grid's options to filter data. For example grid.options.filter, grid.options.paginationCurrentPage, etc can be used.
1

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.