aboutsummaryrefslogtreecommitdiffstats
path: root/src/ng/directive/ngSwitch.js
diff options
context:
space:
mode:
authordanilsomsikov2013-01-11 18:21:13 +0100
committerIgor Minar2013-01-18 00:03:28 -0800
commita26234f7183013e2fcc9b35377e181ad96dc9917 (patch)
tree1c77310d642aea56a72ae0a0fd2b5921919623d6 /src/ng/directive/ngSwitch.js
parent61315211da5d85d73c24169d78e060fb256670e3 (diff)
downloadangular.js-a26234f7183013e2fcc9b35377e181ad96dc9917.tar.bz2
fix(ngSwitch): don't leak when destroyed while not attached
The leak can occur when ngSwich is used inside ngRepeat or any other directive which is destroyed while its transcluded content (which includes ngSwitch) is not attached to the DOM. Refactor ngSwitch to use controller instead of storing data on compile node. This means that we don't need to clean up the jq data cache. Controller reference is released when the linking fn is released. Closes #1621
Diffstat (limited to 'src/ng/directive/ngSwitch.js')
-rw-r--r--src/ng/directive/ngSwitch.js61
1 files changed, 31 insertions, 30 deletions
diff --git a/src/ng/directive/ngSwitch.js b/src/ng/directive/ngSwitch.js
index 0c9e2a8d..24c6047a 100644
--- a/src/ng/directive/ngSwitch.js
+++ b/src/ng/directive/ngSwitch.js
@@ -62,51 +62,52 @@
var NG_SWITCH = 'ng-switch';
var ngSwitchDirective = valueFn({
restrict: 'EA',
- compile: function(element, attr) {
+ require: 'ngSwitch',
+ controller: function ngSwitchController() {
+ this.cases = {};
+ },
+ link: function(scope, element, attr, ctrl) {
var watchExpr = attr.ngSwitch || attr.on,
- cases = {};
+ selectedTransclude,
+ selectedElement,
+ selectedScope;
- element.data(NG_SWITCH, cases);
- return function(scope, element){
- var selectedTransclude,
- selectedElement,
- selectedScope;
-
- scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
- if (selectedElement) {
- selectedScope.$destroy();
- selectedElement.remove();
- selectedElement = selectedScope = null;
- }
- if ((selectedTransclude = cases['!' + value] || cases['?'])) {
- scope.$eval(attr.change);
- selectedScope = scope.$new();
- selectedTransclude(selectedScope, function(caseElement) {
- selectedElement = caseElement;
- element.append(caseElement);
- });
- }
- });
- };
+ scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
+ if (selectedElement) {
+ selectedScope.$destroy();
+ selectedElement.remove();
+ selectedElement = selectedScope = null;
+ }
+ if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {
+ scope.$eval(attr.change);
+ selectedScope = scope.$new();
+ selectedTransclude(selectedScope, function(caseElement) {
+ selectedElement = caseElement;
+ element.append(caseElement);
+ });
+ }
+ });
}
});
var ngSwitchWhenDirective = ngDirective({
transclude: 'element',
priority: 500,
+ require: '^ngSwitch',
compile: function(element, attrs, transclude) {
- var cases = element.inheritedData(NG_SWITCH);
- assertArg(cases);
- cases['!' + attrs.ngSwitchWhen] = transclude;
+ return function(scope, element, attr, ctrl) {
+ ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;
+ };
}
});
var ngSwitchDefaultDirective = ngDirective({
transclude: 'element',
priority: 500,
+ require: '^ngSwitch',
compile: function(element, attrs, transclude) {
- var cases = element.inheritedData(NG_SWITCH);
- assertArg(cases);
- cases['?'] = transclude;
+ return function(scope, element, attr, ctrl) {
+ ctrl.cases['?'] = transclude;
+ };
}
});