Ionic-framework: ion-select delayed population fails to show selected item

Created on 23 Jan 2019  路  10Comments  路  Source: ionic-team/ionic-framework

Bug Report

Ionic version:


[x] 4.x

Current behavior:
Setting the [(ngModel)] on an component fails when there is a ~55 ms or more delay between OnInit and the population of the various elements. This typically occurs when populating the values via an API call but it can be demonstrated with a simple delay. The correct option is selected but not shown. If you click on the drop down caret, the value instantly displays.

Expected behavior:
The component should show the correct value.

Steps to reproduce:
Introduce a 100ms delay between OnInit and populating the control.

Related code:

https://github.com/andleer/ionic4-select-bug/

// with delay, component fails to show selection
setTimeout(() => {
   this.widgets = this.pseudoApiSource;
}, 200);

Other information:

Ionic info:

 cli packages: (C:\Users\andrew\AppData\Roaming\npm\node_modules)

   @ionic/cli-utils  : 2.0.0-rc.3
   ionic (Ionic CLI) : 4.0.0-rc.3

System:

   NodeJS : v10.15.0
   npm    : 6.4.1
   OS     : Windows 10
core bug

Most helpful comment

Adding a 100ms delay after the "api" completes and then setting the selected value causes the selected text to be correctly displayed. Set the value earlier than about 50ms and the update seems to be lost. I have updated the example repo with this delay so it now correctly operates.

I also played with zone.run(() => ... ) and that didn't seem to solve the issue.

setTimeout(() => {
  this.widgets3 = this.pseudoApiSource;
  console.log('widget 3 loaded');
  setTimeout(() => {
    // setting the value here after a delay of about 50ms or more
    // after the "api" call completes
    // causes the selected text to appear correctly.
    // remove the delay and just set the value at the end here
    // and the selected text will fail to display.
    this.selectedWidgetId = 4;
  }, 100);

I now think this is not about the delay driven by an API but rather the lack of a small delay beyond data binding in setting the value. Set it too soon and the selected text will not be updated.

All 10 comments

Adding a 100ms delay after the "api" completes and then setting the selected value causes the selected text to be correctly displayed. Set the value earlier than about 50ms and the update seems to be lost. I have updated the example repo with this delay so it now correctly operates.

I also played with zone.run(() => ... ) and that didn't seem to solve the issue.

setTimeout(() => {
  this.widgets3 = this.pseudoApiSource;
  console.log('widget 3 loaded');
  setTimeout(() => {
    // setting the value here after a delay of about 50ms or more
    // after the "api" call completes
    // causes the selected text to appear correctly.
    // remove the delay and just set the value at the end here
    // and the selected text will fail to display.
    this.selectedWidgetId = 4;
  }, 100);

I now think this is not about the delay driven by an API but rather the lack of a small delay beyond data binding in setting the value. Set it too soon and the selected text will not be updated.

I seemed to have deleted the link to this video of an affected but it looks like you agree that there is an issue

https://youtu.be/BX27D3p78KE

I can approve the issue described here.

ionSelect seems to have another issue.

In our case:
We have two tabs. We fill the ionSelect with an api response

<ion-select
    slot="end"
    placeholder="Select One"
    *ngIf="users.length"
    interface="popover"
    (ionChange)="selectedUser = $event.detail.value"
>
    <ion-select-option [selected]="selectedUser && user.email === selectedUser.email" [value]="user" *ngFor="let user of users">{{user.email}}</ion-select-option>
</ion-select>

This is working on the first view.
Going to tab2 and back to tab1 the ionSelect is visible and also the selected value, but when i open the select nothing is selected and the placeholder is shown.

In our ionViewWillEnter hook we reload the user list.

The only soluation that worked:
Force ionSelect to rerender -> setting the users array empty and wrapt the change of it in a timeout.

This is a little bit frustrating not having selects with dynamic options.

I think i got it. it has something to do with objects as values and the "angular" way to use it if working with ngModel or formControl.

I checked the source of select.

  1. ion-select has also a value-Property --> if this changes the options and everything gets updated ;)
  2. store scalar values as value of the select
  3. first set the ionOptions: first fill the array, where your options come from
  4. then set the value - to trigger the initial update to select the correct option
<ion-select
  slot="end"
  placeholder="Select One"
  *ngIf="users.length"
  interface="popover"
  [value]="selectedUserEmail"
  (ionChange)="buildChart($event.detail.value)"
>
  <ion-select-option [value]="user.email" *ngFor="let user of users">{{user.email}}</ion-select-option>
</ion-select>

No timeout needed anymore.

Wondering if this got a pass and moved to "Needs review"? Anything I can help with?

Hi @andleer,

I have identified the issue and created a fix. I'm just waiting for a review from one of my colleagues.

Hoping to merge soon!

I see the PR out there. Thanks for the attention on this. Kind of a killer for me. Guessing others are affected.

Resolved by 1c9c18b5eaa5807b802829586ec5fffb53f0d345. Will be in the 4.0.2 release today, thanks!

can i reback to ionic v3 ?

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.

Was this page helpful?
0 / 5 - 0 ratings