ionic-framework icon indicating copy to clipboard operation
ionic-framework copied to clipboard

bug: ion select used in array do not update it's value properly

Open JuliaMikov opened this issue 1 year ago • 5 comments

Prerequisites

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

  1. You see 3 ion selects
  2. The second and der third selects are set to value 'B'
  3. Set the second select to 'C'
  4. 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

JuliaMikov avatar Sep 05 '24 08:09 JuliaMikov

Thanks for the issue! Did you provide the wrong StackBlitz link? I only see text and a button.

brandyscarney avatar Sep 05 '24 13:09 brandyscarney

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.

ionitron-bot[bot] avatar Sep 05 '24 13:09 ionitron-bot[bot]

@brandyscarney I am sorry. I froze it without saving. Try it again, please.

JuliaMikov avatar Sep 05 '24 16:09 JuliaMikov

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:

SCR-20240926-mrzo

If you change the middle select box, this will be the state inside of the outer ngFor loop:

SCR-20240926-msml

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.

  1. 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:

image

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.

  1. If you would really want to update the reference of the selections Array 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;
  }

image

Now everything is updated.. I presume step2 is optional based on your needs.

Hope that helps.

berlinjunker avatar Sep 26 '24 12:09 berlinjunker

That looks good! Thank you @berlinjunker for your time and good explanation🤩

JuliaMikov avatar Sep 27 '24 11:09 JuliaMikov

Looks like this was sorted out. Gonna go ahead and close it!

tanner-reits avatar Nov 05 '24 17:11 tanner-reits

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.

ionitron-bot[bot] avatar Dec 05 '24 17:12 ionitron-bot[bot]