Skip to content
This repository has been archived by the owner on Jan 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request angular-ui#3322 from PaulL1/fixes2
Browse files Browse the repository at this point in the history
iPad performance - spare watchers and aggregations
  • Loading branch information
PaulL1 committed Apr 21, 2015
2 parents 5d8221e + 10dc29b commit a45bd8c
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ module.exports = function(grunt) {
version: util.getVersion(),
stable_version: util.getStableVersion(),
dist: 'dist',
site: process.env.TRAVIS ? 'ui-grid.info' : '127.0.0.1:<%= connect.docs.options.port %>',
site: process.env.TRAVIS ? 'ui-grid.info' : '192.168.1.3:<%= connect.docs.options.port %>',
banner: '/*!\n' +
' * <%= pkg.title || pkg.name %> - v<%= version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
Expand Down
25 changes: 25 additions & 0 deletions misc/tutorial/209_grouping.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ counting the number of rows), we find the max age for each grouping, and we calc
suppress the aggregation text on the balance column because we want to format as currency...but that means that
we can't easily see that it's an average.

We write a function that extracts the aggregated data for states and genders (if you change the grouping then this
function will stop working), and writes them to the console.

<example module="app">
<file name="app.js">
var app = angular.module('app', ['ngAnimate', 'ngTouch', 'ui.grid', 'ui.grid.grouping' ]);
Expand Down Expand Up @@ -122,6 +125,27 @@ we can't easily see that it's an average.
$scope.gridApi.grouping.groupColumn('age');
$scope.gridApi.grouping.aggregateColumn('state', uiGridGroupingConstants.aggregation.COUNT);
};

$scope.getAggregates = function() {
var aggregateInfo = {};
var lastState;
$scope.gridApi.grid.renderContainers.body.visibleRowCache.forEach( function(row) {
if( row.groupHeader ) {
if( row.groupLevel === 0 ){
// in the format "xxxxx (10)", we want the xxxx and the 10
if( match = row.entity.state.match(/(.+) \((\d+)\)/) ){
aggregateInfo[ match[1] ] = { stateTotal: match[2] };
lastState = match[1];
}
} else if (row.groupLevel === 1){
if( match = row.entity.gender.match(/(.+) \((\d+)\)/) ){
aggregateInfo[ lastState ][ match[1] ] = match[2];
}
}
}
});
console.log(aggregateInfo);
};
}]);
</file>

Expand All @@ -131,6 +155,7 @@ we can't easily see that it's an average.
<button id="toggleFirstRow" type="button" class="btn btn-success" ng-click="toggleRow(0)">Toggle First Row</button>
<button id="toggleSecondRow" type="button" class="btn btn-success" ng-click="toggleRow(1)">Toggle Second Row</button>
<button id="changeGrouping" type="button" class="btn btn-success" ng-click="changeGrouping()">Change Grouping</button>
<button id="getAggregates" type="button" class="btn btn-success" ng-click="getAggregates()">Get Aggregates</button>
<div id="grid1" ui-grid="gridOptions" ui-grid-grouping class="grid"></div>
</div>
</file>
Expand Down
1 change: 1 addition & 0 deletions misc/tutorial/401_AllFeatures.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ All features are enabled to get an idea of performance
$scope.gridOptions.enableGridMenu = true;
$scope.gridOptions.showGridFooter = true;
$scope.gridOptions.showColumnFooter = true;
$scope.gridOptions.aggregationCalcThrottle = 10000;

$scope.gridOptions.rowIdentity = function(row) {
return row.id;
Expand Down
3 changes: 3 additions & 0 deletions src/js/core/directives/ui-grid-footer-cell.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@
}
});


// Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);
// listen for visible rows change and update aggregation values
$scope.grid.api.core.on.rowsRendered( $scope, $scope.col.updateAggregationValue );

$scope.$on( '$destroy', dataChangeDereg );
}
Expand Down
3 changes: 0 additions & 3 deletions src/js/core/factories/Grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -1314,9 +1314,6 @@ angular.module('ui.grid')
};

Grid.prototype.setVisibleRows = function setVisibleRows(rows) {
// this is also setting processedRows, providing a cache of the rows as they
// came out of the rowProcessors - in particular they are sorted so we
// can process them for grouping
var self = this;

// Reset all the render container row caches
Expand Down
34 changes: 21 additions & 13 deletions src/js/core/factories/GridColumn.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,24 @@ angular.module('ui.grid')

self.aggregationValue = undefined;

var updateAggregationValue = function() {
// The footer cell registers to listen for the rowsRendered event, and calls this. Needed to be
// in something with a scope so that the dereg would get called
self.updateAggregationValue = function() {

// gridUtil.logDebug('getAggregationValue for Column ' + self.colDef.name);

/**
* @ngdoc property
* @name aggregationType
* @propertyOf ui.grid.class:GridOptions.columnDef
* @description The aggregation that you'd like to show in the columnFooter for this
* column. Valid values are in uiGridConstants, and currently include `uiGridConstants.aggregationTypes.count`,
* `uiGridConstants.aggregationTypes.sum`, `uiGridConstants.aggregationTypes.avg`, `uiGridConstants.aggregationTypes.min`,
* `uiGridConstants.aggregationTypes.max`.
*
* You can also provide a function as the aggregation type, in this case your function needs to accept the full
* set of visible rows, and return a value that should be shown
*/
if (!self.aggregationType) {
self.aggregationValue = undefined;
return;
Expand Down Expand Up @@ -173,10 +187,7 @@ angular.module('ui.grid')
}
};

var throttledUpdateAggregationValue = gridUtil.throttle(updateAggregationValue, self.grid.options.aggregationCalcThrottle, { trailing: true });



// var throttledUpdateAggregationValue = gridUtil.throttle(updateAggregationValue, self.grid.options.aggregationCalcThrottle, { trailing: true, context: self.name });

/**
* @ngdoc function
Expand All @@ -186,15 +197,12 @@ angular.module('ui.grid')
* Debounced using scrollDebounce option setting
*/
this.getAggregationValue = function() {
if (!self.grid.isScrollingVertically && !self.grid.isScrollingHorizontally) {
throttledUpdateAggregationValue();
}
// if (!self.grid.isScrollingVertically && !self.grid.isScrollingHorizontally) {
// throttledUpdateAggregationValue();
// }

return self.aggregationValue;
} ;



};
}


Expand Down Expand Up @@ -627,7 +635,7 @@ angular.module('ui.grid')
defaultFilters.push({});
}

/**
/**
* @ngdoc property
* @name filter
* @propertyOf ui.grid.class:GridOptions.columnDef
Expand Down
9 changes: 7 additions & 2 deletions src/js/core/services/ui-grid-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,11 @@ module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateC
* trailing (bool) - whether to trigger after throttle time ends if called multiple times
* Updated to use $interval rather than $timeout, as protractor (e2e tests) is able to work with $interval,
* but not with $timeout
*
* Note that when using throttle, you need to use throttle to create a new function upfront, then use the function
* return from that call each time you need to call throttle. If you call throttle itself repeatedly, the lastCall
* variable will get overwritten and the throttling won't work
*
* @example
* <pre>
* var throttledFunc = gridUtil.throttle(function(){console.log('throttled');}, 500, {trailing: true});
Expand All @@ -1090,12 +1095,12 @@ module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateC
*/
s.throttle = function(func, wait, options){
options = options || {};
var lastCall = 0, queued = null, context, args;
var lastCall = 0, queued = null, context, args, rndFunctionTag = Math.floor(Math.random() * (10000));

function runFunc(endDate){
lastCall = +new Date();
func.apply(context, args);
$interval(function(){ queued = null; }, 0, 1);
$timeout(function(){ queued = null; }, 0);
}

return function(){
Expand Down
48 changes: 48 additions & 0 deletions test/unit/core/factories/GridColumn.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,14 @@ describe('GridColumn factory', function () {

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[0].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[0].getAggregationValue()).toEqual(5);
expect(grid.columns[0].getAggregationText()).toEqual('total rows: ');
deregFn();
});

it('count, without label', function() {
Expand All @@ -203,21 +207,29 @@ describe('GridColumn factory', function () {

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[0].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[0].getAggregationValue()).toEqual(5);
expect(grid.columns[0].getAggregationText()).toEqual('');
deregFn();
});

it('sum, with label', function() {
grid.options.columnDefs[1].aggregationType = uiGridConstants.aggregationTypes.sum;

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[1].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[1].getAggregationValue()).toEqual(15);
expect(grid.columns[1].getAggregationText()).toEqual('total: ');
deregFn();
});

it('sum, without label', function() {
Expand All @@ -226,21 +238,29 @@ describe('GridColumn factory', function () {

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[1].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[1].getAggregationValue()).toEqual(15);
expect(grid.columns[1].getAggregationText()).toEqual('');
deregFn();
});

it('avg, with label', function() {
grid.options.columnDefs[1].aggregationType = uiGridConstants.aggregationTypes.avg;

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[1].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[1].getAggregationValue()).toEqual(3);
expect(grid.columns[1].getAggregationText()).toEqual('avg: ');
deregFn();
});

it('avg, without label', function() {
Expand All @@ -249,21 +269,29 @@ describe('GridColumn factory', function () {

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[1].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[1].getAggregationValue()).toEqual(3);
expect(grid.columns[1].getAggregationText()).toEqual('');
deregFn();
});

it('min, with label', function() {
grid.options.columnDefs[1].aggregationType = uiGridConstants.aggregationTypes.min;

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[1].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[1].getAggregationValue()).toEqual(1);
expect(grid.columns[1].getAggregationText()).toEqual('min: ');
deregFn();
});

it('min, without label', function() {
Expand All @@ -272,21 +300,29 @@ describe('GridColumn factory', function () {

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[1].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[1].getAggregationValue()).toEqual(1);
expect(grid.columns[1].getAggregationText()).toEqual('');
deregFn();
});

it('max, with label', function() {
grid.options.columnDefs[1].aggregationType = uiGridConstants.aggregationTypes.max;

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[1].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[1].getAggregationValue()).toEqual(5);
expect(grid.columns[1].getAggregationText()).toEqual('max: ');
deregFn();
});

it('max, without label', function() {
Expand All @@ -295,10 +331,14 @@ describe('GridColumn factory', function () {

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[1].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[1].getAggregationValue()).toEqual(5);
expect(grid.columns[1].getAggregationText()).toEqual('');
deregFn();
});

it('max, with custom label', function() {
Expand All @@ -310,10 +350,14 @@ describe('GridColumn factory', function () {

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[1].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[1].getAggregationValue()).toEqual(5);
expect(grid.columns[1].getAggregationText()).toEqual(customLabel);
deregFn();
});

it('max, with custom label while also being hidden', function() {
Expand All @@ -325,10 +369,14 @@ describe('GridColumn factory', function () {

buildCols();
grid.modifyRows(grid.options.data);

// this would be called by the footer cell if it were rendered
var deregFn = grid.api.core.on.rowsRendered(null, grid.columns[1].updateAggregationValue);
grid.setVisibleRows(grid.rows);

expect(grid.columns[1].getAggregationValue()).toEqual(5);
expect(grid.columns[1].getAggregationText()).toEqual('');
deregFn();
});
});

Expand Down

0 comments on commit a45bd8c

Please sign in to comment.