Skip to content

fix(5007): Reduced the amount of digest cycles initiated by the grid. #6072

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 15, 2017

Conversation

mportuga
Copy link
Member

Re-implemented some of @csvan's work with PR #5829 and improved refreshCanvas function.
Also, update the All features tutorial to add a toggle button for the filter row and improved coverage in ui-grid.js

5007

Re-implemented some of @csvan's work with PR angular-ui#5829 and improved refreshCanvas function.

5007
@mportuga mportuga requested review from dlgski and jeremytowne March 13, 2017 20:22
return row.id;
var gridApi;

$scope.gridOptions = {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to combine the multiple calls to $scope.gridOptions.[something] into one object definition.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea


$scope.gridOptions.columnDefs = [
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This moved to line 31

};
$scope.gridOptions.getRowIdentity = function(row) {

function getRowId(row) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function was repeated for getRowIndentity and rowIdentity, so I combined them.

}]);
</file>
<file name="index.html">
<div ng-controller="MainCtrl">
<button id="filterToggle" type="button" class="btn btn-success" ng-click="toggleFilterRow()">Toggle Filter</button>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find myself needing to test this a lot and I frequently see question about how to implement something like this, so I added it to this demo.

$attrs.$observe('uiGridColumns', function(value) {
self.grid.options.columnDefs = value;
deregFunctions.push( $attrs.$observe('uiGridColumns', function(value) {
self.grid.options.columnDefs = angular.isString(value) ? angular.fromJson(value) : value;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While writing unit tests, I realized there was a mistake with this watch. Since this is an attribute watch, the value of it might be a string that needs to be converted to an object.

}

// prevents an error from being thrown when the array is not defined yet and fastWatch is on
function getSize(array) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, while writing unit tests, I realized we don't handle the case for where data is undefined and fastWatch is on. This will prevent issues with that.

else {
$timeout(init);
} else {
$scope.$applyAsync(init);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should prevent an unnecessary digest cycle by pig backing on the next available cycle.

// Bind to window resize events
angular.element($window).on('resize', gridResize);

// Unbind from window resize events when the grid is destroyed
$elm.on('$destroy', function () {
angular.element($window).off('resize', gridResize);
deregisterLeftWatcher();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaning up possible memory leaks

@@ -595,10 +595,10 @@ angular.module('ui.grid')
callback.types.indexOf( type ) !== -1 ||
type === uiGridConstants.dataChange.ALL ) {
if (callback._this) {
callback.callback.apply(callback._this,this);
callback.callback.apply(callback._this, this, options);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Giving us a way to pass options into a registered callback. This allowed me to prevent buildColumns from being triggered multiple time during initialization. See line 74 of ui-grid.js


self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN);
}).catch(angular.noop);
self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN, {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prevent buildColumns from being triggered multiple time during initialization. See lines 598 and 601 of Grid.js.

@@ -84,12 +84,10 @@
// gridUtil.logDebug('dataWatch fired');
var promises = [];

if ( self.grid.options.fastWatch ){
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the fastWatch condition for expecting data to be a string because based on line 62 of this file, strings for data are supported without fastWatch.


self.grid.preCompileCellTemplates();

self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line was causing buildColumns to be triggered a second time.

Grid.prototype.columnRefreshCallback = function columnRefreshCallback( grid ){
grid.buildColumns();
Grid.prototype.columnRefreshCallback = function columnRefreshCallback(grid, options){
grid.buildColumns(options);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows the columnRefreshCallback to pre-compile the cell templates when needed.

@@ -664,7 +664,7 @@
allowCellFocus: true
};

uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef, 0);
uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef, 0, true);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a new attribute to prevent build columns from being triggered multiple times in a row. ColumnDefs is now responsible for building the columns. See line 763 of Grid.js

@@ -715,7 +715,7 @@
};

rowHeaderColumnDef.visible = grid.options.treeRowHeaderAlwaysVisible;
grid.addRowHeaderColumn( rowHeaderColumnDef, -100 );
grid.addRowHeaderColumn(rowHeaderColumnDef, -100, true);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a new attribute to prevent build columns from being triggered multiple times in a row. ColumnDefs is now responsible for building the columns. See line 763 of Grid.js

@derekm
Copy link

derekm commented Mar 13, 2017

I was just noticing the massive amount of digest cycles that ui-grid forces, especially in my case when I'm swapping large datasets in and out while using ui-grid-auto-resize to make all rows visible.

@csvan
Copy link
Contributor

csvan commented Mar 14, 2017

@mportuga great work!

return row.id;
var gridApi;

$scope.gridOptions = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea

$scope.toggleFilterRow = function() {
$scope.gridOptions.enableFiltering = !$scope.gridOptions.enableFiltering;
gridApi.core.notifyDataChange(uiGridConstants.dataChange.COLUMN);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is this used? Is it a new button designed into the grid? Why do you need to notifyDataChange?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is a new button. And the grid will not update unless the event is fired.

@mportuga mportuga merged commit bd51855 into angular-ui:master Mar 15, 2017
@mportuga mportuga deleted the fix/performance branch March 15, 2017 01:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants