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

Angular 1.6 incorrectly resets <select>'s ng-model` value #15630

Closed
th0r opened this issue Jan 20, 2017 · 3 comments
Closed

Angular 1.6 incorrectly resets <select>'s ng-model` value #15630

th0r opened this issue Jan 20, 2017 · 3 comments

Comments

@th0r
Copy link

th0r commented Jan 20, 2017

Note: for support questions, please use one of these channels: https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#question. This repository's issues are reserved for feature requests and bug reports.

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
Angular 1.6 resets <select>s ng-model value when <option>s list changes (see "Other information" section).
Angular 1.5 preserves it.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://plnkr.co or similar (template: http://plnkr.co/edit/tpl:yBpEi4).
Angular 1.6: https://plnkr.co/edit/wHc4rzy7x9PAEqQLfVQT?p=preview
Angular 1.5.11: https://plnkr.co/edit/e0LVMEtGP2j4JxNf8lsp?p=preview

What is the expected behavior?
ng-model preserves it's value.

What is the motivation / use case for changing the behavior?
It's not correct.

Which versions of Angular, and which browser / OS are affected by this issue? Did this work in previous versions of Angular? Please also test with the latest stable and snapshot (https://code.angularjs.org/snapshot/) versions.
Angular 1.6.x is affected.
Angular 1.5.x is not.

Other information (e.g. stacktraces, related issues, suggestions how to fix)
The thing is Angular 1.6 tracks options by it's model and not by the optionss value.

In the snippets above options array contains 2 objects: [{val: "1"}, {val: "2"}].
ng-repeat iterates through them and uses val property as both option value and title.
vm.selected is used as select's ng-model value and is initially set to "2".

After pressing Change options button I replace options array with this one: [{val: "2"}, {val: "3"}] and Angular 1.6 resets vm.selected value but it shouldn't because option with value 2 is still in the list.

Angular 1.5 behaves correctly in this case and vm.selected value is preserved.

If vm.options contains primitive values bug doesn't appear (snippet).

@gkalpak
Copy link
Member

gkalpak commented Jan 20, 2017

Seems like a valid issue and it breaks in 1.6.0-rc.0. Not sure why it didn't happen before, but the issue seems to be this:

  1. When the array changes, ngRepeat removes the previous <option> elements.
  2. This causes the <select> to get unselected and ngModel to be set to null.
  3. The new items are created and inserted by ngRepeat, but the modelValue is not 2 any more, so <select> has no way to associate it with the new <option value="2" ...>.

A work-around is to use track by to avoid destroying and recreating the <option> elements:

<option ng-repeat="option in options track by option.val" value="option.val">...

from a quick look, the following commits are candidates for having caused this (but it could be something else):

Off the top of my head, I would start by replacing this line with scheduleRender() and see if it helps...

I am sure @Narretz will have some better insights 😃

@th0r
Copy link
Author

th0r commented Jan 20, 2017

A work-around is to use track by to avoid destroying and recreating the elements

Yes, found it out too but forgot to mention 😏

@Narretz
Copy link
Contributor

Narretz commented Jan 20, 2017

Looks like this was an intentional change in 47c15fb: "- when an option that is currently selected, is removed or its value changes, the model is set to null." but this didn't take into account that this might be breaking, or that ngRepeat would take a digest to update the options. It's also easier to do in ngOptions because we control the creation / destruction of elements.
But scheduleRender() works, yay for @gkalpak ! I'll see if it breaks tests and prepare a PR.

@Narretz Narretz self-assigned this Jan 20, 2017
Narretz added a commit to Narretz/angular.js that referenced this issue Jan 20, 2017
Narretz added a commit to Narretz/angular.js that referenced this issue Jan 26, 2017
Narretz added a commit to Narretz/angular.js that referenced this issue Jan 26, 2017
ellimist pushed a commit to ellimist/angular.js that referenced this issue Mar 15, 2017
odedniv pushed a commit to odedniv/angular.js that referenced this issue Apr 14, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants