Skip to content

Commit

Permalink
feat(Core): Implementation for #2483. Adds a showGridFooter option th…
Browse files Browse the repository at this point in the history
…at will create a grid footer with the Total Items and Shown Items displayed. Also shows Selected Items if using Selection feature.

BREAKING CHANGE: showFooter option renamed to showColumnFooter;  footerRowHeight option renamed to columnFooterHeight
  • Loading branch information
swalters committed Jan 9, 2015
1 parent 30df7d4 commit d023360
Show file tree
Hide file tree
Showing 21 changed files with 295 additions and 70 deletions.
3 changes: 2 additions & 1 deletion misc/site/index.html
Expand Up @@ -245,7 +245,8 @@ <h4 class="feature-heading">Complex Example</h4>

$rootScope.gridOptionsComplex = {
enableFiltering: true,
showFooter: true,
showGridFooter: true,
showColumnFooter: true,
columnDefs: [
{ name: 'name', aggregationType: uiGridConstants.aggregationTypes.count, width: 150 },
{ name: 'gender', filter: { term: 'male' }, width: 150, enableCellEdit: false,
Expand Down
20 changes: 15 additions & 5 deletions misc/tutorial/105_footer.ngdoc
Expand Up @@ -2,7 +2,12 @@
@name Tutorial: 105 Footer
@description

The grid supports a footer row, which can be displayed if showFooterRow option is set to true.
### Grid Footer
The grid supports a grid footer row, which can be displayed if showGridFooter option is set to true (default=false). This footer displays
Total rows in the grid and the number of filtered rows. Selected rows will be shown if using ui-grid-selection feature.
<br/>
### Column Footer
The grid also has column footer, which can be displayed if showColumnFooter option is set to true (default=false).
You can set an aggregation function for each column or use a custom footer template to display
what ever aggregation you wish.
Aggregation functions supported are: sum, avg, row count, min, max.
Expand All @@ -23,18 +28,22 @@ You can override the default grid footer template with gridOptions.footerTemplat
var data = [];

$scope.gridOptions = {
showFooter: true,
showGridFooter: true,
showColumnFooter: true,
enableFiltering: true,
columnDefs: [
{ field: 'name', aggregationType: uiGridConstants.aggregationTypes.count, width: '13%' },
{ field: 'name', width: '13%' },
{ field: 'address.street',aggregationType: uiGridConstants.aggregationTypes.sum, width: '13%' },
{ field: 'age', aggregationType: uiGridConstants.aggregationTypes.avg, aggregationHideLabel: true, width: '13%' },
{ name: 'ageMin', field: 'age', aggregationType: uiGridConstants.aggregationTypes.min, width: '13%', displayName: 'Age for min' },
{ name: 'ageMax', field: 'age', aggregationType: uiGridConstants.aggregationTypes.max, width: '13%', displayName: 'Age for max' },
{ name: 'customCellTemplate', field: 'age', width: '14%', footerCellTemplate: '<div class="ui-grid-cell-contents" style="background-color: Red;color: White">custom template</div>' },
{ name: 'registered', field: 'registered', width: '20%', cellFilter: 'date', footerCellFilter: 'date', aggregationType: uiGridConstants.aggregationTypes.max }
],
data: data
data: data,
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
}
}

$http.get('/data/500_complex.json')
Expand All @@ -48,7 +57,8 @@ You can override the default grid footer template with gridOptions.footerTemplat
</file>
<file name="index.html">
<div ng-controller="MainCtrl">
<button id="footerButton" class="btn btn-success" ng-click="gridOptions.showFooter = !gridOptions.showFooter">Toggle Footer</button>
<button id="footerButton" class="btn btn-success" ng-click="gridOptions.showGridFooter = !gridOptions.showGridFooter; $scope.gridApi.core.notifyDataChange($scope.gridApi.grid, uiGridConstants.dataChange.OPTIONS);">Toggle Grid Footer</button>
<button class="btn btn-success" ng-click="gridOptions.showColumnFooter = !gridOptions.showColumnFooter; $scope.gridApi.core.notifyDataChange($scope.gridApi.grid, uiGridConstants.dataChange.OPTIONS);">Toggle Column Footer</button>
<div id="grid1" ui-grid="gridOptions" class="grid"></div>
</div>
</file>
Expand Down
3 changes: 2 additions & 1 deletion misc/tutorial/210_selection.ngdoc
Expand Up @@ -47,7 +47,8 @@ Two examples are provided, the first with rowHeaderSelection and multi-select, t
$scope.gridOptions = {
enableRowSelection: true,
enableSelectAll: true,
selectionRowHeaderWidth: 35
selectionRowHeaderWidth: 35,
showGridFooter:true
};

$scope.gridOptions.columnDefs = [
Expand Down
10 changes: 7 additions & 3 deletions misc/tutorial/401_AllFeatures.ngdoc
Expand Up @@ -13,14 +13,17 @@ All features are enabled to get an idea of performance
<file name="app.js">
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.cellNav', 'ui.grid.edit', 'ui.grid.resizeColumns', 'ui.grid.pinning', 'ui.grid.selection', 'ui.grid.moveColumns']);

app.controller('MainCtrl', ['$scope', '$http', '$timeout', '$interval', function ($scope, $http, $timeout, $interval) {
app.controller('MainCtrl', ['$scope', '$http', '$timeout', '$interval', 'uiGridConstants',
function ($scope, $http, $timeout, $interval, uiGridConstants) {

$scope.gridOptions = {};
$scope.gridOptions.data = 'myData';
$scope.gridOptions.enableColumnResizing = true;
$scope.gridOptions.enableFiltering = true;
$scope.gridOptions.enableGridMenu = true;

$scope.gridOptions.showGridFooter = true;
$scope.gridOptions.showColumnFooter = true;

$scope.gridOptions.rowIdentity = function(row) {
return row.id;
};
Expand All @@ -31,7 +34,8 @@ All features are enabled to get an idea of performance
$scope.gridOptions.columnDefs = [
{ name:'id', width:50 },
{ name:'name', width:100 },
{ name:'age', width:100, enableCellEdit: true, cellTemplate: '<div class="ui-grid-cell-contents"><span>Age:{{COL_FIELD}}</span></div>' },
{ name:'age', width:100, enableCellEdit: true, aggregationType:uiGridConstants.aggregationTypes.avg,
cellTemplate: '<div class="ui-grid-cell-contents"><span>Age:{{COL_FIELD}}</span></div>' },
{ name:'address.street', width:150, enableCellEdit: true, cellTemplate: '<div class="ui-grid-cell-contents"><span>Street:{{COL_FIELD}}</span></div>' },
{ name:'address.city', width:150, enableCellEdit: true, cellTemplate: '<div class="ui-grid-cell-contents"><span>City:{{COL_FIELD}}</span></div>' },
{ name:'address.state', width:50, enableCellEdit: true, cellTemplate: '<div class="ui-grid-cell-contents"><span>State:{{COL_FIELD}}</span></div>' },
Expand Down
144 changes: 120 additions & 24 deletions src/features/selection/js/selection.js
Expand Up @@ -27,6 +27,58 @@
selectionRowHeaderColName: 'selectionRowHeaderCol'
});

//add methods to GridRow
angular.module('ui.grid').config(['$provide', function($provide) {
$provide.decorator('GridRow', ['$delegate', function($delegate) {

/**
* @ngdoc object
* @name ui.grid.selection.api:GridRow
*
* @description GridRow prototype functions added for selection
*/

/**
* @ngdoc object
* @name enableSelection
* @propertyOf ui.grid.selection.api:GridRow
* @description Enable row selection for this row, only settable by internal code.
*
* The grouping feature, for example, might set group header rows to not be selectable.
* <br/>Defaults to true
*/

/**
* @ngdoc object
* @name isSelected
* @propertyOf ui.grid.selection.api:GridRow
* @description Selected state of row. Should be readonly. Make any changes to selected state using setSelected().
* <br/>Defaults to false
*/


/**
* @ngdoc function
* @name setSelected
* @methodOf ui.grid.selection.api:GridRow
* @description Sets the isSelected property and updates the selectedCount
* Changes to isSelected state should only be made via this function
* @param {bool} selelected value to set
*/
$delegate.prototype.setSelected = function(selected) {
this.isSelected = selected;
if (selected) {
this.grid.selection.selectedCount++;
}
else {
this.grid.selection.selectedCount--;
}
};

return $delegate;
}]);
}]);

/**
* @ngdoc service
* @name ui.grid.selection.service:uiGridSelectionService
Expand All @@ -40,11 +92,28 @@

initializeGrid: function (grid) {

//add feature namespace and any properties to grid for needed state
//add feature namespace and any properties to grid for needed
/**
* @ngdoc object
* @name ui.grid.selection.grid:selection
*
* @description Grid properties and functions added for selection
*/
grid.selection = {};
grid.selection.lastSelectedRow = null;
grid.selection.selectAll = false;


/**
* @ngdoc object
* @name selectedCount
* @propertyOf ui.grid.selection.grid:selection
* @description Current count of selected rows
* @example
* var count = grid.selection.selectedCount
*/
grid.selection.selectedCount = 0;

service.defaultGridOptions(grid.options);

/**
Expand Down Expand Up @@ -157,7 +226,7 @@
var changedRows = [];
grid.rows.forEach(function (row) {
if ( !row.isSelected && row.enableSelection !== false ){
row.isSelected = true;
row.setSelected(true);
service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
}
});
Expand All @@ -180,12 +249,12 @@
grid.rows.forEach(function (row) {
if (row.visible) {
if (!row.isSelected && row.enableSelection !== false){
row.isSelected = true;
row.setSelected(true);
service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
}
} else {
if (row.isSelected){
row.isSelected = false;
row.setSelected(false);
service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
}
}
Expand Down Expand Up @@ -276,23 +345,6 @@
* set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
*/

/**
* @ngdoc object
* @name ui.grid.selection.api:GridRow
*
* @description GridRow options for selection feature
*/
/**
* @ngdoc object
* @name enableSelection
* @propertyOf ui.grid.selection.api:GridRow
* @description Enable row selection for this row, only settable by internal code.
*
* The grouping feature, for example, might set group header rows to not be selectable.
* <br/>Defaults to true
*/


/**
* @ngdoc object
* @name enableRowSelection
Expand Down Expand Up @@ -363,6 +415,16 @@
* <br/>Defaults to 30px
*/
gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;

/**
* @ngdoc object
* @name enableFooterTotalSelected
* @propertyOf ui.grid.selection.api:GridOptions
* @description Shows the total number of selected items in footer if true.
* <br/>Defaults to true.
* <br/>GridOptions.showFooter must also be set to true.
*/
gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;
},

/**
Expand Down Expand Up @@ -392,7 +454,7 @@
if (selected && noUnselect){
// don't deselect the row
} else if (row.enableSelection !== false) {
row.isSelected = !selected;
row.setSelected(!selected);
if (row.isSelected === true) {
grid.selection.lastSelectedRow = row;
} else {
Expand Down Expand Up @@ -430,7 +492,7 @@
var rowToSelect = grid.renderContainers.body.visibleRowCache[i];
if (rowToSelect) {
if ( !rowToSelect.isSelected && rowToSelect.enableSelection !== false ){
rowToSelect.isSelected = true;
rowToSelect.setSelected(true);
grid.selection.lastSelectedRow = rowToSelect;
service.decideRaiseSelectionEvent( grid, rowToSelect, changedRows, evt );
}
Expand Down Expand Up @@ -463,7 +525,7 @@
var changedRows = [];
service.getSelectedRows(grid).forEach(function (row) {
if ( row.isSelected ){
row.isSelected = false;
row.setSelected(false);
service.decideRaiseSelectionEvent( grid, row, changedRows, evt );
}
});
Expand Down Expand Up @@ -757,4 +819,38 @@
};
}]);

module.directive('uiGridGridFooter', ['$compile', 'uiGridConstants', 'gridUtil', function ($compile, uiGridConstants, gridUtil) {
return {
restrict: 'EA',
replace: true,
priority: -1000,
require: '^uiGrid',
scope: true,
compile: function ($elm, $attrs) {
return {
pre: function ($scope, $elm, $attrs, uiGridCtrl) {

if (!uiGridCtrl.grid.options.showGridFooter) {
return;
}


gridUtil.getTemplate('ui-grid/gridFooterSelectedItems')
.then(function (contents) {
var template = angular.element(contents);

var newElm = $compile(template)($scope);

angular.element($elm[0].getElementsByClassName('ui-grid-grid-footer')[0]).append(newElm);
});
},

post: function ($scope, $elm, $attrs, controllers) {

}
};
}
};
}]);

})();
@@ -0,0 +1 @@
<span ng-if="grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected">({{"search.selectedItems" | t}} {{grid.selection.selectedCount}})</span>
4 changes: 3 additions & 1 deletion src/features/selection/test/uiGridSelectionService.spec.js
Expand Up @@ -17,7 +17,7 @@ describe('ui.grid.selection uiGridSelectionService', function () {
$templateCache.put('ui-grid/uiGridCell', '<div/>');
$templateCache.put('ui-grid/editableCell', '<div editable_cell_directive></div>');

grid = gridClassFactory.createGrid({});
grid = gridClassFactory.createGrid({showGridFooter:true});
grid.options.columnDefs = [
{field: 'col1', enableCellEdit: true}
];
Expand Down Expand Up @@ -108,6 +108,7 @@ describe('ui.grid.selection uiGridSelectionService', function () {
expect(grid.rows[3].isSelected).toBe(true);
expect(grid.rows[4].isSelected).toBe(true);
expect(grid.rows[5].isSelected).toBe(true);
expect(grid.selection.selectedCount).toBe(4);
});

it('should skip non-selectable rows', function () {
Expand Down Expand Up @@ -240,6 +241,7 @@ describe('ui.grid.selection uiGridSelectionService', function () {
expect(grid.rows[8].isSelected).toBe(undefined);
expect(grid.rows[9].isSelected).toBe(true);
expect(grid.selection.selectAll).toBe(true);
expect(grid.selection.selectedCount).toBe(8);
});
});

Expand Down
38 changes: 38 additions & 0 deletions src/js/core/directives/ui-grid-grid-footer.js
@@ -0,0 +1,38 @@
(function () {
'use strict';

angular.module('ui.grid').directive('uiGridGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {
var defaultTemplate = 'ui-grid/ui-grid-grid-footer';

return {
restrict: 'EA',
replace: true,
// priority: 1000,
require: '^uiGrid',
scope: true,
compile: function ($elm, $attrs) {
return {
pre: function ($scope, $elm, $attrs, uiGridCtrl) {

$scope.grid = uiGridCtrl.grid;
$scope.getExternalScopes = uiGridCtrl.getExternalScopes;

var footerTemplate = ($scope.grid.options.gridFooterTemplate) ? $scope.grid.options.gridFooterTemplate : defaultTemplate;
gridUtil.getTemplate(footerTemplate)
.then(function (contents) {
var template = angular.element(contents);

var newElm = $compile(template)($scope);
$elm.append(newElm);
});
},

post: function ($scope, $elm, $attrs, controllers) {

}
};
}
};
}]);

})();
2 changes: 1 addition & 1 deletion src/js/core/directives/ui-grid-native-scrollbar.js
Expand Up @@ -122,7 +122,7 @@
var w = colContainer.getCanvasWidth();

var bottom = gridBottomBorder;
if (grid.options.showFooter) {
if (grid.hasFooter()) {
bottom -= 1;
}

Expand Down

0 comments on commit d023360

Please sign in to comment.