Ionic 4 - ion-select 不会滚动到警报中的 selected 项目

Ionic 4 - ion-select does not scroll to selected item in alert

我正在使用 ionic 4.7.0

我报告的问题发生在 Chrome 和 Firefox 上。

实际行为:

使用带有大量选项的 ion-select,当您打开警报时,ion-select 不会自动滚动到 selected 值。用户看到选项列表中的第一个值,他可能认为没有 selected

预期行为:

打开警报时,视图会自动以 selected 值

为中心

我创建这个 stackblitz 来突出显示该行为,我们可以在加载视图时在 stackblitz 上看到,selected 值为 11:00 但是当您打开警报时(通过单击 ion-select),我希望视图在 selected 值上自动滚动。

这是 ion-select 的预期行为吗?

我发现了几个关于同一主题但没有真正回答问题的问题:

这目前不是 Ionic 中的功能,但有一个 open issue。点赞提高优先级。

目前您可以使用解决方法:

window.addEventListener('ionAlertDidPresent', e => {
  const selected = (e.target as HTMLElement).querySelector('[aria-checked="true"]');
  selected && selected.scrollIntoView();
});

每次预设警报时都会触发此侦听器。然后它使用 aria-checked HTML 属性查找(第一个)选定元素并将其滚动到视图中。

您可能想看看 the parameters for scrollIntoView(),例如滚动以使所选项目位于底部。

要仅影响 ion-select 警报,您可以检查警报是否具有 select-alert(或 single-select-alert)class。要只影响单个警报,您可以通过在 ion-select.

interfaceOptions 属性 中传递它来为警报指定一个 ID

如前所述,这是一种解决方法,如果组件发生变化,可能会停止工作。

我最近重写了我们的 autoscroll 指令,所以我想在这里分享它。它适用于所有 IonSelect 界面(Alert、Popover 和 ActionSheet)。

import { Directive, HostListener } from '@angular/core';
import { IonSelect } from '@ionic/angular';

/**
 * Autoscroll to the selected option of an ion-select when opened.
 */
@Directive({
  selector: 'ion-select[autoscroll]'
})
export class AutoscrollSelectDirective {

  constructor(
    private ionSelect: IonSelect
  ) {}

  @HostListener('click')
  scrollSoon(): void {
    let keBab = '';
    switch (this.ionSelect.interface) {
      case 'alert': keBab = 'Alert'; break;
      case 'action-sheet': keBab = 'ActionSheet'; break;
      case 'popover': keBab = 'Popover'; break;
    }

    if (keBab) {
      window.addEventListener(
        `ion${keBab}DidPresent`,
        e => {
          const parent: Element = <any>e.target;
          const scrollTarget = keBab === 'ActionSheet'
              ? parent.querySelector('.action-sheet-selected')
              : parent.querySelector('[aria-checked=true]')?.closest('.select-interface-option');
          if (scrollTarget) {
            scrollTarget.scrollIntoView();
          }
        },
        {once: true}
      );
    }
  }

}