Skip to content

Commit

Permalink
fix(uiGrid): Fix race condition in data watcher
Browse files Browse the repository at this point in the history
The data watch function is creating a condition where promises can get
resolved out of order. If you are fetching both cell templates and data
over the network, it will operate thusly:

1. Data watch fires with empty data array, it sees there's no columns set
up and builds them from the columnDefs. This uses a promise from the
preCompileCellTemplates function.
2. The new data comes in, the data watcher sees there's columns set up now
so nothing has to be done and it sets the rows to your new data. Yay!
3. The promise from preCompileCellTemplates completes, and the data is
updated AGAIN, but this time with the original empty data set, blowing
away the data you fetched.

This fix changes the operation so we only call buildColumnDefsFromData()
when we actually HAVE data to use, and buildColumns() gets called if we
either have data OR have columnDefs.

Fixes #2053
  • Loading branch information
c0bra committed Nov 13, 2014
1 parent 75bd9f0 commit 2b25f24
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions src/js/core/directives/ui-grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,36 @@
}
}

function dataWatchFunction(n) {
function dataWatchFunction(newData) {
// gridUtil.logDebug('dataWatch fired');
var promises = [];

if (n) {
if (self.grid.columns.length === ( self.grid.rowHeaderColumns ? self.grid.rowHeaderColumns.length : 0 ) ) {
// gridUil.logDebug('loading cols in dataWatchFunction');
if (!$attrs.uiGridColumns && self.grid.options.columnDefs.length === 0) {
self.grid.buildColumnDefsFromData(n);
}
if (newData) {
if (
// If we have no columns (i.e. columns length is either 0 or equal to the number of row header columns, which don't count because they're created automatically)
self.grid.columns.length === (self.grid.rowHeaderColumns ? self.grid.rowHeaderColumns.length : 0) &&
// ... and we don't have a ui-grid-columns attribute, which would define columns for us
!$attrs.uiGridColumns &&
// ... and we have no pre-defined columns
self.grid.options.columnDefs.length === 0 &&
// ... but we DO have data
n.length > 0
) {
// ... then build the column definitions from the data that we have
self.grid.buildColumnDefsFromData(n);
}

// If we either have some columns defined, or some data defined
if (self.grid.options.columnDefs.length > 0 || newData.length > 0) {
// Build the column set, then pre-compile the column cell templates
promises.push(self.grid.buildColumns()
.then(function() {
self.grid.preCompileCellTemplates();}
));
self.grid.preCompileCellTemplates();
}));
}

$q.all(promises).then(function() {
self.grid.modifyRows(n)
self.grid.modifyRows(newData)
.then(function () {
// if (self.viewport) {
self.grid.redrawInPlace();
Expand Down

0 comments on commit 2b25f24

Please sign in to comment.