fix(ngSwitch): use the correct transclusion scope

If an ngSwitchWhen or ngSwitchDefault directive is on an element that also
contains a transclusion directive (such as ngRepeat) the new scope should
be the one provided by the bound transclusion function.

Previously we were incorrectly creating a simple child of the main ngSwitch
scope.

BREAKING CHANGE:
** Directive Priority Changed ** - this commit changes the priority
of `ngSwitchWhen` and `ngSwitchDefault` from 800 to 1200.  This makes their
priority higher than `ngRepeat`, which allows items to be repeated on
the switch case element reliably.

In general your directives should have a lower priority than these directives
if you want them to exist inside the case elements. If you relied on the
priority of these directives then you should check that your code still
operates correctly.

Closes #8235
This commit is contained in:
Peter Bacon Darwin
2014-07-17 20:07:46 +01:00
parent 81d9193ed7
commit 4f32e3eef1
2 changed files with 27 additions and 6 deletions

View File

@@ -166,9 +166,8 @@ var ngSwitchDirective = ['$animate', function($animate) {
if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
scope.$eval(attr.change);
forEach(selectedTranscludes, function(selectedTransclude) {
var selectedScope = scope.$new();
selectedScopes.push(selectedScope);
selectedTransclude.transclude(selectedScope, function(caseElement) {
selectedTransclude.transclude(function(caseElement, selectedScope) {
selectedScopes.push(selectedScope);
var anchor = selectedTransclude.element;
selectedElements.push(caseElement);
@@ -183,7 +182,7 @@ var ngSwitchDirective = ['$animate', function($animate) {
var ngSwitchWhenDirective = ngDirective({
transclude: 'element',
priority: 800,
priority: 1200,
require: '^ngSwitch',
multiElement: true,
link: function(scope, element, attrs, ctrl, $transclude) {
@@ -194,7 +193,7 @@ var ngSwitchWhenDirective = ngDirective({
var ngSwitchDefaultDirective = ngDirective({
transclude: 'element',
priority: 800,
priority: 1200,
require: '^ngSwitch',
multiElement: true,
link: function(scope, element, attr, ctrl, $transclude) {

View File

@@ -241,7 +241,7 @@ describe('ngSwitch', function() {
$rootScope.url = 'x';
$rootScope.$apply();
expect(getChildScope()).toBeUndefined();
expect(child1.$destroy).toHaveBeenCalledOnce();
expect(child1.$destroy).toHaveBeenCalled();
$rootScope.url = 'a';
$rootScope.$apply();
@@ -251,6 +251,28 @@ describe('ngSwitch', function() {
}));
it("should use the correct transclusion scope if there is a transclude directive on the ng-swith-when/ng-switch-default element", inject(function($rootScope, $compile) {
element = $compile(
'<div ng-switch="foo">' +
'<pre ng-switch-when="item1" ng-repeat="bar in bars">' +
'foo = {{foo}}' +
'bar = {{bar}}' +
'$index = {{$index}}' +
'</pre>' +
'</div>'
)($rootScope);
$rootScope.$apply('foo="item1";bars=["one", "two"]');
expect(element.text()).toEqual(
'foo = item1' +
'bar = one' +
'$index = 0' +
'foo = item1' +
'bar = two' +
'$index = 1'
);
}));
it('should not leak jq data when compiled but not attached to parent when parent is destroyed',
inject(function($rootScope, $compile) {
element = $compile(