ionic-framework
ionic-framework copied to clipboard
bug: ion select used in array do not update it's value properly
Prerequisites
- [X] I have read the Contributing Guidelines.
- [X] I agree to follow the Code of Conduct.
- [X] I have searched for existing issues that already report this problem, without success.
Ionic Framework Version
v7.x
Current Behavior
I have three ion select components which created out of an array. If two of them have the same value and I change the first one, both of them take the new value.
Expected Behavior
If one value in array was changed only the related ion select should be updated.
Steps to Reproduce
- You see 3 ion selects
- The second and der third selects are set to value 'B'
- Set the second select to 'C'
- Both: the second and the third select set to C now, although the array is set to [ 'A', 'C', 'B']
Code Reproduction URL
https://stackblitz.com/edit/ionic6-angular13-ghkmsb?file=src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.module.ts
Ionic Info
Ionic:
Ionic CLI : 6.16.3 (/usr/local/lib/node_modules/@ionic/cli) Ionic Framework : not installed @angular-devkit/build-angular : 17.3.8 (/Users/jmikov/Projects/lbs/lbs-sales/node_modules/@angular-devkit/build-angular) @angular-devkit/schematics : 17.3.8 (/Users/jmikov/Projects/lbs/lbs-sales/node_modules/@angular-devkit/schematics) @angular/cli : 17.3.8 (/Users/jmikov/Projects/lbs/lbs-sales/node_modules/@angular/cli) @ionic/angular-toolkit : 11.0.1 (/Users/jmikov/Projects/lbs/lbs-sales/node_modules/@ionic/angular-toolkit)
Capacitor:
Capacitor CLI : not installed @capacitor/android : 6.1.0 (/Users/jmikov/Projects/lbs/lbs-sales/node_modules/@capacitor/android) @capacitor/core : 6.1.0 (/Users/jmikov/Projects/lbs/lbs-sales/node_modules/@capacitor/core) @capacitor/ios : 6.1.0 (/Users/jmikov/Projects/lbs/lbs-sales/node_modules/@capacitor/ios)
Utility:
cordova-res : not installed globally native-run : not installed globally
System:
NodeJS : v18.18.2 (/Users/jmikov/.nvm/versions/node/v18.18.2/bin/node) npm : 10.2.5 OS : macOS
Additional Information
No response
Thanks for the issue! Did you provide the wrong StackBlitz link? I only see text and a button.
Thanks for the issue! This issue has been labeled as needs reproduction. This label is added to issues that need a code reproduction.
Please reproduce this issue in an Ionic starter application and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.
If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.
For a guide on how to create a good reproduction, see our Contributing Guide.
@brandyscarney I am sorry. I froze it without saving. Try it again, please.
I believe that here is some misunderstanding concerning Angular ChangeDetection related to Object-references.
I try to explain:
First of all your outer array is being passed by reference since Arrays are Objects. That means without a reassignment from the variable selections you wont trigger the ChangeDetection Cycle, so that wont update correctly since you are only modifying one index of this array without changing the whole thing.
You can see this by printing the selections array for each ion-select and observe the state while you change some of the inputs.
Initial:
If you change the middle select box, this will be the state inside of the outer ngFor loop:
As you can observe, the selections array has changed for the instance of that ion-select loop and the endresult, but for the other loops it stayed the same. As the ChangeDetection is not able to figure out, what in the DOM has changed, it will rerender the whole loop, as soon as something will change inside your selection array and indeed, it results into this strange behaviour, that the third ion-select shows the wrong letter as well - but whole state is kind of broken at this point.
How to solve this now:
There are two approaches which probably should be used altogether.
- Use a trackBy Function in order to help ChangeDetection, to update only the DOM elements that actually have changed.
You can add something like this:
- In your template update your *ngFor Directive
*ngFor="let selection of selections; let i = index; trackBy:trackById" - Create a trackById function in your component-class:
trackById(index, item) { return index; }
Result would be this, after change of the second ion-select:
Only the outer selections array has changed.. not the inner ones.. - that is good, only the ion-select updates it value based on what you have selected. At this point you could move on, since your selections Array has the correct value and your display is representing what the values are.
- If you would really want to update the reference of the
selectionsArray inside the loop, you have to replace that reference with a clone of that array.
That can be done when your change Event triggers and you are calling your function changeSelection(event: any, index: number):
changeSelection(event: any, index: number) {
this.selections[index] = event?.detail.value;
const newSelections = Array.from(this.selections);
this.selections = newSelections;
}
Now everything is updated.. I presume step2 is optional based on your needs.
Hope that helps.
That looks good! Thank you @berlinjunker for your time and good explanation🤩
Looks like this was sorted out. Gonna go ahead and close it!
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.