diff --git a/src/js/core/directives/ui-grid-header-cell.js b/src/js/core/directives/ui-grid-header-cell.js index 41ff42e02a..d3a70585e1 100644 --- a/src/js/core/directives/ui-grid-header-cell.js +++ b/src/js/core/directives/ui-grid-header-cell.js @@ -1,8 +1,8 @@ (function() { 'use strict'; - angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService', - function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService) { + angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService', '$rootScope', + function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService, $rootScope) { // Do stuff after mouse has been down this many ms on the header cell var mousedownTimeout = 500, changeModeTimeout = 500; // length of time between a touch event and a mouse event being recognised again, and vice versa @@ -226,6 +226,35 @@ } }; + var setFilter = function (updateFilters) { + if ( updateFilters ) { + if ( typeof($scope.col.updateFilters) !== 'undefined' ) { + $scope.col.updateFilters($scope.col.filterable); + } + + // if column is filterable add a filter watcher + if ($scope.col.filterable) { + $scope.col.filters.forEach( function(filter, i) { + filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) { + if (n !== o) { + uiGridCtrl.grid.api.core.raise.filterChanged(); + uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN ); + uiGridCtrl.grid.queueGridRefresh(); + } + })); + }); + $scope.$on('$destroy', function() { + filterDeregisters.forEach( function(filterDeregister) { + filterDeregister(); + }); + }); + } else { + filterDeregisters.forEach( function(filterDeregister) { + filterDeregister(); + }); + } + } + }; var updateHeaderOptions = function() { var contents = $elm; @@ -254,36 +283,12 @@ $scope.sortable = Boolean($scope.col.enableSorting); // Figure out whether this column is filterable or not - var oldFilterable = $scope.filterable; - $scope.filterable = Boolean(uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering); - - if ( oldFilterable !== $scope.filterable) { - if ( typeof($scope.col.updateFilters) !== 'undefined' ) { - $scope.col.updateFilters($scope.filterable); - } + var oldFilterable = $scope.col.filterable; + $scope.col.filterable = Boolean(uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering); - // if column is filterable add a filter watcher - if ($scope.filterable) { - $scope.col.filters.forEach( function(filter, i) { - filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) { - if (n !== o) { - uiGridCtrl.grid.api.core.raise.filterChanged(); - uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN ); - uiGridCtrl.grid.queueGridRefresh(); - } - })); - }); - $scope.$on('$destroy', function() { - filterDeregisters.forEach( function(filterDeregister) { - filterDeregister(); - }); - }); - } else { - filterDeregisters.forEach( function(filterDeregister) { - filterDeregister(); - }); - } - } + $scope.$applyAsync(function () { + setFilter(oldFilterable !== $scope.col.filterable); + }); // figure out whether we support column menus $scope.colMenu = ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false && @@ -328,6 +333,14 @@ updateHeaderOptions(); + if ($scope.col.filterContainer === 'columnMenu' && $scope.col.filterable) { + $rootScope.$on('menu-shown', function() { + $scope.$applyAsync(function () { + setFilter($scope.col.filterable); + }); + }); + } + // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]); diff --git a/src/js/core/directives/ui-grid-menu.js b/src/js/core/directives/ui-grid-menu.js index 6650fede48..d3bd328a77 100644 --- a/src/js/core/directives/ui-grid-menu.js +++ b/src/js/core/directives/ui-grid-menu.js @@ -37,7 +37,8 @@ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18 scope: { // shown: '&', menuItems: '=', - autoHide: '=?' + autoHide: '=?', + col: '=?' }, require: '?^uiGrid', templateUrl: 'ui-grid/uiGridMenu', @@ -157,8 +158,15 @@ function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18 // *** Auto hide when click elsewhere ****** - var applyHideMenu = function() { + var applyHideMenu = function(event) { if ($scope.shown) { + if ($scope.col && $scope.col.filterContainer === 'columnMenu') { + var elm = document.querySelector('.ui-grid-column-menu').querySelector('[ui-grid-filter]'); + if (elm && elm.contains(event.target)) { + return false; + } + } + $scope.$apply(function () { $scope.hideMenu(); }); diff --git a/src/js/core/factories/GridColumn.js b/src/js/core/factories/GridColumn.js index f4429d2dab..b6bcd15d7e 100644 --- a/src/js/core/factories/GridColumn.js +++ b/src/js/core/factories/GridColumn.js @@ -751,6 +751,9 @@ angular.module('ui.grid') // Turn on filtering by default (it's disabled by default at the Grid level) self.enableFiltering = typeof(colDef.enableFiltering) !== 'undefined' ? colDef.enableFiltering : true; + // Place the filter in the header cell by default + self.filterContainer = typeof(colDef.filterContainer) !== 'undefined' ? colDef.filterContainer : self.grid.options.filterContainer; + // self.menuItems = colDef.menuItems; self.setPropertyOrDefault(colDef, 'menuItems', []); diff --git a/src/js/core/factories/GridOptions.js b/src/js/core/factories/GridOptions.js index 4dca7f729b..4be3cd7b5e 100644 --- a/src/js/core/factories/GridOptions.js +++ b/src/js/core/factories/GridOptions.js @@ -387,6 +387,17 @@ angular.module('ui.grid') */ baseOptions.enableFiltering = baseOptions.enableFiltering === true; + /** + * @ngdoc string + * @name filterContainer + * @propertyOf ui.grid.class:GridOptions + * @description Sets the parent element for the column filter. `headerCell` places + * it in the header cell. `columnMenu` places it in the column menu. + * Can be changed for individual columns using the columnDefs. + * Defaults to `headerCell` + */ + baseOptions.filterContainer = typeof(baseOptions.filterContainer) !== "undefined" ? baseOptions.filterContainer : "headerCell"; + /** * @ngdoc boolean * @name enableColumnMenus diff --git a/src/templates/ui-grid/uiGridColumnMenu.html b/src/templates/ui-grid/uiGridColumnMenu.html index 370f8ef7a7..23714a207d 100644 --- a/src/templates/ui-grid/uiGridColumnMenu.html +++ b/src/templates/ui-grid/uiGridColumnMenu.html @@ -1,5 +1,5 @@
-
+