Ionic-framework: ion-select not scrolling to selected option.

Created on 28 Apr 2016  路  12Comments  路  Source: ionic-team/ionic-framework

Short description of the problem:

When using the ion-select can the already selected option be scrolled into view? In the below example 2016 was already selected, but is not initially shown when opening the select alert because it is the last option in the ion-select.

image

What behavior are you expecting?

When a select is opened the selected option should be scrolled into view:

image

Which Ionic Version? 2.x

stale issue

Most helpful comment

@russcarver thanks for the tip--your August 21 comment got me on the right path.

I came to a similar solution:

    setTimeout(() => {
      document.getElementsByClassName('alert-radio-group')[0]
              .querySelector('[aria-checked="true"]')
              .scrollIntoView();
    }, 500);

I don't love that we're just guessing at how long it will take for the alert to render... is there some sort of callback or event we can use to know when it's loaded? In my case also the alert is being generated by an ion-select tag.

All 12 comments

Any progress on this?

Strange, I don't understand how the current behavior is accepted? I find it very confusing not to see the currently selected option when I open a dropdown; it makes it look like nothing is selected.

In other words, this is a (UX) bug and I believe it should be treated as such.

Yeah, I believe I had to fix this with a javascript scrollIntoView.

@russcarver Can you show an example of how you did it?

Here is my current solution in Angular4/Ionic3:

<ion-item color="primary" class="primary-background-transparent">
  <ion-label>State</ion-label>
  <ion-select class="form-select" [selectOptions]="stateOptions" [(ngModel)]="state"
       [ngModelOptions]="{standalone: true}" (ionChange)="stateChanged(state)" 
       (click)="onSelectClicked()">
    <ion-option *ngFor="let state of states">{{state}}</ion-option>
  </ion-select>
</ion-item>
  public onSelectClicked (): void {
    const options: HTMLCollectionOf<Element> = document.getElementsByClassName('alert-tappable alert-radio') // These classes come from the generated elements for the ion-select/ion-option
    setTimeout(() => {
      let i: number = 0
      const len: number = options.length
      for (i; i < len; i++) {
        if ((options[i] as HTMLElement).attributes[3].nodeValue === 'true') {
          options[i].scrollIntoView({ block: 'end', behavior: 'smooth' })
        }
      }
    }, 500) // Leave enough time for the popup to render
  }

Thanks a lot for the workaround! I hope they get this issue fixed soon ;)

@russcarver If you want to avoid using the 500ms as a hack, you can also modify your version to listen to when the popup has opened:

<ion-item color="primary" class="primary-background-transparent">
  <ion-label>State</ion-label>
  <ion-select #selectElement class="form-select" [selectOptions]="stateOptions" [(ngModel)]="state"
       [ngModelOptions]="{standalone: true}" (ionChange)="stateChanged(state)" 
       (click)="onSelectClicked(selectElement)">
    <ion-option *ngFor="let state of states">{{state}}</ion-option>
  </ion-select>
</ion-item>
public onSelectClicked(selectButton: Select): void {
    const options: HTMLCollectionOf<Element> = document.getElementsByClassName('alert-tappable alert-radio'); // These classes come from the generated elements for the ion-select/ion-option
    (<any>selectButton._overlay).didEnter.subscribe(
      () => {
        //Give a one cycle delay just to run this just after the didEnter has been called
        setTimeout(() => {
          let i: number = 0
          const len: number = options.length
          for (i; i < len; i++) {
            if ((options[i] as HTMLElement).attributes[3].nodeValue === 'true') {
              options[i].scrollIntoView({ block: 'end', behavior: 'instant' })
            }
          }
        });
      }
    );
  }

The setTimeout on this solution is not time dependent but just a hacky way of skipping one processing cycle. I tested on multiple devices and it worked ;)

@russcarver thanks for the tip--your August 21 comment got me on the right path.

I came to a similar solution:

    setTimeout(() => {
      document.getElementsByClassName('alert-radio-group')[0]
              .querySelector('[aria-checked="true"]')
              .scrollIntoView();
    }, 500);

I don't love that we're just guessing at how long it will take for the alert to render... is there some sort of callback or event we can use to know when it's loaded? In my case also the alert is being generated by an ion-select tag.

@soynog Take a look at the comment above yours. I just adjusted @russcarver code to use the callback from when the popup has loaded. It is hacky and also needs you to declare one selector for each ion-select that you have in your view, but it solves the problem of being dependent on the performance of the device.

Ixnay on my previous note about waiting to load the alert... looks like @Artfloriani has a solution to that. Awesome!

Lol, lags.

Thanks for the issue! This issue is being closed due to inactivity. 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.

Thank you for using Ionic!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexbainbridge picture alexbainbridge  路  3Comments

giammaleoni picture giammaleoni  路  3Comments

gio82 picture gio82  路  3Comments

SebastianGiro picture SebastianGiro  路  3Comments

masimplo picture masimplo  路  3Comments