Skip to content

Commit 64d3918

Browse files
committed
fix(uiGridRow): Fix memory leak
Bindings were being attached to the uiGridRow scope but never removed because the scope was not being destroyed even though child elements were being added. This was fixed by creating new scopes for uiGridRow when compiled/re-compiled. Also, added an element-based `$destroy` handler for ui-grid-cell. It already had one for the $scope.
1 parent a547a52 commit 64d3918

File tree

2 files changed

+21
-8
lines changed

2 files changed

+21
-8
lines changed

src/js/core/directives/ui-grid-cell.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ angular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUt
8787
rowWatchDereg();
8888
};
8989

90-
9190
$scope.$on( '$destroy', deregisterFunction );
91+
$elm.on( '$destroy', deregisterFunction );
9292
}
9393
};
9494
}

src/js/core/directives/ui-grid-row.js

+20-7
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,26 @@
2424
$scope.colContainer = containerCtrl.colContainer;
2525

2626
// Function for attaching the template to this scope
27+
var clonedElement, cloneScope;
2728
function compileTemplate() {
2829
var compiledElementFn = $scope.row.compiledElementFn;
2930

30-
compiledElementFn($scope, function (clonedElement, scope) {
31-
$elm.empty().append(clonedElement);
31+
// Create a new scope for the contents of this row, so we can destroy it later if need be
32+
var newScope = $scope.$new();
33+
34+
compiledElementFn(newScope, function (newElm, scope) {
35+
// If we already have a cloned element, we need to remove it and destroy its scope
36+
if (clonedElement) {
37+
clonedElement.remove();
38+
cloneScope.$destroy();
39+
}
40+
41+
// Empty the row and append the new element
42+
$elm.empty().append(newElm);
43+
44+
// Save the new cloned element and scope
45+
clonedElement = newElm;
46+
cloneScope = newScope;
3247
});
3348
}
3449

@@ -38,18 +53,16 @@
3853
// If the row's compiled element function changes, we need to replace this element's contents with the new compiled template
3954
$scope.$watch('row.compiledElementFn', function (newFunc, oldFunc) {
4055
if (newFunc !== oldFunc) {
41-
newFunc($scope, function (clonedElement, scope) {
42-
$elm.empty().append(clonedElement);
43-
});
56+
compileTemplate();
4457
}
4558
});
4659
},
4760
post: function($scope, $elm, $attrs, controllers) {
4861
var uiGridCtrl = controllers[0];
4962
var containerCtrl = controllers[1];
5063

51-
//add optional reference to externalScopes function to scope
52-
//so it can be retrieved in lower elements
64+
// Sdd optional reference to externalScopes function to scope
65+
// so it can be retrieved in lower elements
5366
$scope.getExternalScopes = uiGridCtrl.getExternalScopes;
5467
}
5568
};

0 commit comments

Comments
 (0)