fix(ngIf): destroy child scope when destroying DOM

This commit is contained in:
Igor Minar 2013-11-04 10:28:30 -08:00
parent c6923d2df4
commit 9483373c33
2 changed files with 40 additions and 12 deletions

View file

@ -87,23 +87,31 @@ var ngIfDirective = ['$animate', function($animate) {
$$tlb: true,
compile: function (element, attr, transclude) {
return function ($scope, $element, $attr) {
var block = {}, childScope;
var block, childScope;
$scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
if (block.startNode) {
$animate.leave(getBlockElements(block));
block = {};
}
if (block.startNode) {
getBlockElements(block).$destroy();
block = {};
}
if (toBoolean(value)) {
childScope = $scope.$new();
transclude(childScope, function (clone) {
block.startNode = clone[0];
block.endNode = clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
block = {
startNode: clone[0],
endNode: clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ')
};
$animate.enter(clone, $element.parent(), $element);
});
} else {
if (childScope) {
childScope.$destroy();
childScope = null;
}
if (block) {
$animate.leave(getBlockElements(block));
block = null;
}
}
});
};

View file

@ -36,7 +36,7 @@ describe('ngIf', function () {
expect(element.children().length).toBe(0);
});
it('should create a new scope', function () {
it('should create a new scope every time the expression evaluates to true', function () {
$scope.$apply('value = true');
element.append($compile(
'<div ng-if="value"><span ng-init="value=false"></span></div>'
@ -45,6 +45,26 @@ describe('ngIf', function () {
expect(element.children('div').length).toBe(1);
});
it('should destroy the child scope every time the expression evaluates to false', function() {
$scope.value = true;
element.append($compile(
'<div ng-if="value"></div>'
)($scope));
$scope.$apply();
var childScope = element.children().scope();
var destroyed = false;
childScope.$on('$destroy', function() {
destroyed = true;
});
$scope.value = false;
$scope.$apply();
expect(destroyed).toBe(true);
});
it('should play nice with other elements beside it', function () {
$scope.values = [1, 2, 3, 4];
element.append($compile(