-
Notifications
You must be signed in to change notification settings - Fork 27.4k
ngOptions with "track by" triggers ngChange when ngModel did not change #11936
Comments
Hi, thanks for the detailed bug report. In the plnkr, I can't see ngChange being triggered after the plnkr is initalized. (I put a console.log inside the makeModelChanged fn) Is there something missing? |
Hi, thanks for having a look. I have added a console.log to make it clear when ngChange is triggered and also to show when the controller is created and destroyed. The problem occurs when the controller is created and the ngModels have valid values, not when they are undefined. The 'Remove' checkbox is there to toggle the existence of the controller using ng-if. These are the steps to recreate the issue, including the
It is the last console log |
Thanks, that clears it up! Would you like to take a shot at a PR with your suggested fix? |
I will be away for a week, but if it hasn't been resolved by someone else by then, I will give it a go. |
Change the check on changed value for ngOptions to ensure that a reference check is only done when trackBy is not used. Previously, if trackBy was being used but the values of the objects were equal a reference check was then used which would cause the check to be true if the objects had different memory references but the values were equal. This can cause issues with forms being marked dirty when the value of the model as not actually changed. Closes angular#11936
Change the check on changed value for ngOptions to ensure that a reference check is only done when trackBy is not used. Previously, if trackBy was being used but the values of the objects were equal a reference check was then used which would cause the check to be true if the objects had different memory references but the values were equal. This can cause issues with forms being marked dirty when the value of the model as not actually changed. Closes angular#11936
Change the check on changed value for ngOptions to ensure that a reference check is only done when trackBy is not used. Previously, if trackBy was being used but the values of the objects were equal a reference check was then used which would cause the check to be true if the objects had different memory references but the values were equal. This can cause issues with forms being marked dirty when the value of the model as not actually changed. Closes angular#11936 Closes angular#11996
Seeing this while using an Angular Material select box as well. Angular version 1.4.5. Wondering if there's a workaround in the meantime? |
This should be fixed in 1.4. Can you show a demo? |
Overview of the Issue
vm.options is an array of objects with a unique id property. When the
<select>
is first created, ngChange is triggered if ngModel is an object that does not have the same reference as any of the objects in vm.options even though it may be identical in value to one of them. As there has not been a change to the ngModel value, it is not expected that ngChange is triggered.Motivation for or Use Case
There are two
<select>
elements for the user to select the make and model of a car. The options available for<select>
model are dependent on the selected value in<select>
make. Therefore, when the selected value in<select>
make changes, the selected value in<select>
model should be cleared. This works with no issues. However, when navigating away from and back to the<select>
elements, the<select>
model is cleared even though the value of<select>
make did not change. This is not expected.Angular Version(s)
This issue does not occur with version 1.3.15 through to 1.4.0-beta.6
This issue does occur with versions 1.4.0-rc.0 through to at least 1.4.0-rc.2
Browsers and Operating System
Chrome 43.0.2357.65 m, Firefox 38.0.1, IE 11.0.9600.17801
Windows 8.1 Pro
Reproduce the Error
http://plnkr.co/edit/xe4HPLZVEHqO7XYW1kGX?p=preview
Related Issues
#11448
#11447
Suggest a Fix
The issue seems to result from this commit: 171b9f7
In the code below, when
previousValue !== nextValue
is true,ngModelCtrl.$setViewValue(nextValue)
is invoked, even thoughngOptions.trackBy
is true and!equals(previousValue, nextValue)
is false.The code to compare previousValue and nextValue could be changed to:
This would result in a deep comparison when track by is used and a reference comparison when track by is not used.
The text was updated successfully, but these errors were encountered: