Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

ngSwitchWhen element eats ngRepeat's child scope #8235

Closed
ttencate opened this issue Jul 17, 2014 · 25 comments
Closed

ngSwitchWhen element eats ngRepeat's child scope #8235

ttencate opened this issue Jul 17, 2014 · 25 comments

Comments

@ttencate
Copy link

Scope:

{
  foo: 'value',
  bars: ['one', 'two'],
}

HTML:

<div ng-switch="foo">
    <pre ng-switch-when="value" ng-repeat="bar in bars">
        foo = {{foo}}
        bar = {{bar}}
        $index = {{$index}}
    </pre>
</div>

Fiddle: http://jsfiddle.net/y68sy/1/ (http://jsfiddle.net/PqLmp/)

Expected output:

    foo = value
    bar = one
    $index = 0

    foo = value
    bar = two
    $index = 1

Actual output:

    foo = value
    bar = 
    $index = 

    foo = value
    bar = 
    $index = 

So the ngRepeat works in the sense that the element is repeated, but the inner scope is wrong; it does not contain the values that ngRepeat puts into it.

This happens because ngSwitch creates a new child scope that inherits from the ngSwitch's scope, not from the ngSwitchWhen's scope:

var selectedScope = scope.$new();

I'm not sure if this is expected behaviour, or whether it can be fixed without breaking something else.

@caitp
Copy link
Contributor

caitp commented Jul 17, 2014

well it's pretty clearly not a behaviour which makes sense to a programmer, but I think it's somewhat more complicated than described here. @petebacondarwin wdyt?

@petebacondarwin
Copy link
Contributor

I think this is a bug. We had to change ngIf to deal with this sort of thing: see https://github.com/angular/angular.js/blob/master/src/ng/directive/ngIf.js#L93. Here we let the transclusion provide the scope.

@petebacondarwin
Copy link
Contributor

@caitp
Copy link
Contributor

caitp commented Jul 17, 2014

@petebacondarwin does the change pass tests there? if so we should probably fix this soon

@petebacondarwin
Copy link
Contributor

I'll check today and put together a fix
On 17 Jul 2014 14:29, "Caitlin Potter" notifications@github.com wrote:

@petebacondarwin https://github.com/petebacondarwin does the change
pass tests there? if so we should probably fix this soon


Reply to this email directly or view it on GitHub
#8235 (comment).

@Narretz Narretz added this to the 1.3.0 milestone Jul 17, 2014
@Narretz
Copy link
Contributor

Narretz commented Jul 17, 2014

Meta: @petebacondarwin @caitp Aren't we supposed to only label with one of severity? Because it's a degree, not a type.

@caitp
Copy link
Contributor

caitp commented Jul 17, 2014

these are qualitative measures, and they're all applicable here.

@Narretz
Copy link
Contributor

Narretz commented Jul 17, 2014

Really, I need no idea. https://github.com/angular/angular.js/blob/master/TRIAGING.md doesn't mention it, and that's also not how I understood it when Brian explained it to me.

@caitp
Copy link
Contributor

caitp commented Jul 17, 2014

I should add, "in my opinion" --- I don't believe "broken expected use case" is any more "severe" than "confusing" or "inconvenient". The fact is, this is a broken expected use case (we know this because it seems totally natural to want to use it this way), it's confusing because it's kind of hard to even reason about why this doesn't work as expected, and it's inconvenient because it requires you to work around the limitations of the compiler with hacks.

I believe each of these are qualities applicable to this issue, and I would not be able to say that any of them are more severe than any of the others.

But really, label it however you like --- these seem reasonable to me, I don't care a whole lot if we take some out

@petebacondarwin
Copy link
Contributor

@caitp - I believe that @btford's whizzy spreadsheet makes use of these labels and so I expect it will only pick one - hopefully the most severe!

petebacondarwin added a commit to petebacondarwin/angular.js that referenced this issue Jul 17, 2014
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.

Closes angular#8235
@lgalfaso
Copy link
Contributor

@petebacondarwin I think that the version from #8235 (comment) is problematic as making it work just for this case gives some false hope that this will work for all cases and that it works like what people expect from ng-repeat
E.g.
http://plnkr.co/edit/VuaLYHTbX2qV2qyfU4ow?p=preview

@lgalfaso
Copy link
Contributor

To make this case work as expected, then we need to make the priority of ng-switch-when higher than ng-repeat. E.g.
http://plnkr.co/edit/YOYPd9hvhq9OUDC42UjQ?p=preview

@btford
Copy link
Contributor

btford commented Jul 17, 2014

meta: I label with just the "highest severity." The prioritization dashboard assumes you do this. If something is a "broken expected use," then it's almost assuredly going to be "confusing" to developers and also "inconvenient." Of course these qualitative measures are not mutually exclusive, but the idea is that cases where something doesn't work when it reasonably seems like it should are worse than cases where it's somewhat unclear why something works a certain way. Put another way, I consider flagrant violations of a developers expectations to be more severe than edge cases with unexpected behavior. I amended the triaging doc with these notes. If anyone wants to continue the discussion of our triaging process, let's open a new issue for that.

@petebacondarwin
Copy link
Contributor

Thanks @lgalfaso - I will add a test and fix up. I believe that both fixes are needed, no?

@lgalfaso
Copy link
Contributor

@petebacondarwin yes, both fixes are needed

@petebacondarwin
Copy link
Contributor

@lgalfaso - I can't see where you changed that to make it work in that plunk??

@petebacondarwin
Copy link
Contributor

Oh, OK, so you changed ngRepeat priorty from 1000 to 700?

@lgalfaso
Copy link
Contributor

@petebacondarwin change the priority of ng-repeat to 700 (anyhow, now I think it would be better to change the priority of ng-switch-when to 1200)

@petebacondarwin
Copy link
Contributor

And ngSwitchDefault too.

@petebacondarwin
Copy link
Contributor

The question is will that break some other use case? I can't think of one since we don't allow ngSwitchWhen to take dynamic values, so people wouldn't be able to generate a bunch of different ngSwitchWhen elements using ngRepeat...

@lgalfaso
Copy link
Contributor

I can't think of anything that will break (and as you mention, the fact that ng-switch-when does not allow dynamic values is key)

@petebacondarwin
Copy link
Contributor

Actually this whole thing is broken if you have ngSwitchWhen and ngSwitchDefault with ngRepeats mixed in: http://plnkr.co/edit/lcJH1E3H6r3hynoO5iT0?p=preview

:-(

@lgalfaso
Copy link
Contributor

@petebacondarwin it looks like ng-switch needs the same care as ng-if. Look at
http://plnkr.co/edit/hefdNeuoEEifEvgUCE7y?p=preview

@petebacondarwin
Copy link
Contributor

Yes I agree I was just doing that refactoring :-)

petebacondarwin added a commit to petebacondarwin/angular.js that referenced this issue Jul 17, 2014
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.

Closes angular#8235
petebacondarwin added a commit to petebacondarwin/angular.js that referenced this issue Jul 17, 2014
@petebacondarwin
Copy link
Contributor

Closing in favour of #8244

petebacondarwin added a commit to petebacondarwin/angular.js that referenced this issue Jul 18, 2014
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 angular#8235
petebacondarwin added a commit to petebacondarwin/angular.js that referenced this issue Jul 18, 2014
petebacondarwin added a commit that referenced this issue Jul 18, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.