aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ng/directive/ngSwitch.js61
-rw-r--r--test/ng/directive/ngSwitchSpec.js15
2 files changed, 46 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;
+ };
}
});
diff --git a/test/ng/directive/ngSwitchSpec.js b/test/ng/directive/ngSwitchSpec.js
index 66ae5562..ee91f79d 100644
--- a/test/ng/directive/ngSwitchSpec.js
+++ b/test/ng/directive/ngSwitchSpec.js
@@ -90,4 +90,19 @@ describe('ngSwitch', function() {
expect(child2).toBeDefined();
expect(child2).not.toBe(child1);
}));
+
+
+ it('should not leak jq data when compiled but not attached to parent when parent is destroyed',
+ inject(function($rootScope, $compile) {
+ element = $compile(
+ '<div ng-repeat="i in []">' +
+ '<ng-switch on="url">' +
+ '<div ng-switch-when="a">{{name}}</div>' +
+ '</ng-switch>' +
+ '</div>')($rootScope);
+ $rootScope.$apply();
+
+ // element now contains only empty repeater. this element is dealocated by local afterEach.
+ // afterwards a global afterEach will check for leaks in jq data cache object
+ }));
});