angular: docs: clarify ivy breaking change for `ngFor` and `
` with animations and no `trackBy` 🐞 bug report Affected Package The issue seems to be related to package @angular/platform-browser Is this a regression? Yes, the previous version in which this bug was not present was: v8.* (8.2.14) Description Upgrading to Angular v9 broke the functionality of <select> for us. The *ngFor directive we use for populating it with <option> elements now all of the sudden re-renders items if you simply refresh the collection with new instances, even if their contents are the same. This resets the selected option, which is not expected and not desirable. This wasn’t happening in v8. This isn’t happening in v9 either, unless BrowserAnimationsModule is imported by the app-module. This also can be worked around by using trackBy, but for that you’d need to track down all the problematic ngFor directives after upgrading to v9. 🔬 Minimal Reproduction Click here for v9 repro repository Click here to see the same v9 repro app in action Same demo working without problems in Angular v8 - although StackBlitz doesn’t have this problem with v9 either (not sure why), but at least helps illustrate how it was working before The v9 repro is based on ng new of Angular CLI 9.0.5. If building yourself, run locally with ng serve, because if imported into StackBlitz, the issue can’t be reproduced. Choose an item in any drop down (the two are linked and simply illustrate the trackBy difference) Notice that the first button adds a new item but the selected option doesn’t get reset. Clicking the second button though resets the selected option in the first drop down. 🔥 Exception or Error None 🌍 Your Environment Angular Version: Angular CLI: 9.0.5 Node: 10.16.3 OS: win32 x64 Angular: 9.0.5 ... animations, cli, common, compiler, compiler-cli, core, forms ... language-service, platform-browser, platform-browser-dynamic ... router Ivy Workspace: Yes Package Version ----------------------------------------------------------- @angular-devkit/architect 0.900.5 @angular-devkit/build-angular 0.900.5 @angular-devkit/build-optimizer 0.900.5 @angular-devkit/build-webpack 0.900.5 @angular-devkit/core 9.0.5 @angular-devkit/schematics 9.0.5 @ngtools/webpack 9.0.5 @schematics/angular 9.0.5 @schematics/update 0.900.5 rxjs 6.5.4 typescript 3.7.5 webpack 4.41.2 Anything else relevant? Happens only in Angular v9, when BrowserAnimationsModule is imported into AppModule and ngFor is not set up with trackBy. About this issue Original URL State: closed Created 4 years ago Reactions: 3 Comments: 17 (8 by maintainers) Commits related to this issue fix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years agofix(forms): ensure that selected option element matches the ngModel value Given the following component: @Component({ selector: 'ng-model-select-form', template: ` <select [(... — committed to theodorejb/angular by theodorejb 4 years ago Most upvoted comments I’m re-opening this issue while we discuss the best way to tackle this. This change was expected based on how Ivy works (so trackBy seems like a good fix), but I agree the experience is confusing and there’s probably a way to make it less painful for users. +5 kara on May 27, 2020 This is still happening on Angular 9.1.3. Without using trackBy, when assigning a new list to the *ngFor list in a select, it sets the select back to the default value ‘’, but the form contains the correct id and the formControlName is not working with select correctly. Also figured out BrowserAnimationsModule is the cause of this when adding to AppModule +5 xonuzofa on Apr 28, 2020 This appears to be related to the breaking change related to insertion order (reference): Embedded views (such as ones created by *ngFor) are now inserted in front of anchor DOM comment node (e.g. ) rather than behind it as was the case previously. In most cases this does not have any impact on rendered DOM. In some cases (such as animations delaying the removal of an embedded view) any new embedded views will be inserted after the embedded view being animated away. This difference only last while the animation is active, and might alter the visual appearance of the animation. Once the animation is finished the resulting rendered DOM is identical to that rendered with View Engine. In the stackblitz example, you can see that when Ivy is disabled, the new items are added to the front of the list (add a break on: subtree modifications to the dom). If you go to the settings in stackblitz and check the box to “Enable Ivy”, you’ll see that new items are added to the end of the list. To clarify, both Ivy and View Engine are re-rendering the items because you don’t have trackBy. The difference is the location of the newly inserted items. Because BrowserAnimationsModule queues up the removal of the old items in order to animate them, you will briefly have duplicate items in the list if you don’t use trackBy. In the Ivy example, since the old items being removed are above the new items, when they’re removed, the browser sees this as the selected item being removed. As a quick fix, I would recommend using trackBy to avoid this issue. +3 atscott on May 24, 2021 I could not tell you if this is really a bug or a feature of the v9 nevertheless the trackBy feature is dedicated to avoid re-rendering the DOM to improve the performances. It seems to me that you should have used a trackBy and your issue is in fact, a bad design from your project. Even if Angular considers it as a bug, you should really use the trackBy anytime it is possible. +3 C0ZEN on Mar 6, 2020 It looks like there’s attention and progress on this bug. If a fix is found, is there any chance it could be introduced with a minor or patch update in the near future, since it’s clearly a significant regression bug? Or would it more likely have to wait until the Angular 10 release? I’m just trying to gauge the likelihood that it will be fixed within our development window, or whether I should be looking to implement trackBy in all the places where we have issues. +1 Da13Harris on Jun 11, 2020 @matsko and @atscott - I wonder if it could be possible to identify such cases and provide a migration to help? +1 petebacondarwin on May 27, 2020 Read more comments on GitHub ← angular: docs: Add documentation for `error NG2007: Ignore abstract classes` angular: docs: Style Guide's "Directive selectors" doesn't mention prefixing selectors → Table of contents Issue description Related commits Top comments About this issue Original URL State: closed Created 4 years ago Reactions: 3 Comments: 17 (8 by maintainers)