Material Angular 滚动到 mat-list 上的元素

Old*_*han 6 scroll material-design angular-material angular

我有一个包含多个元素的 Angular Material 列表,其中可以选择其中之一。

当我加载此列表时,我想将列表向上滚动到所选元素,以使其更加可见。有什么选择吗?

我正在考虑在 ngOnInit 中检查是否选择了项目,但我真的不知道如何将此列表滚动到该项目。

注意:不应滚动整个页面,只应滚动列表中的元素。

组件.html

    <mat-nav-list>
        <mat-list-item *ngFor="let item of items" (click)="itemClick(item)"
            [ngClass]="item.selectedClass">
            {{item.someValue}}
        </mat-list-item>
    </mat-nav-list>
Run Code Online (Sandbox Code Playgroud)

组件.ts

    private itemClick(item: Item): Observable<any> {
        if (item) {
            this.something = item;
            this.items.forEach(item => {
                if (item && item.name === item.name) {
                    item["selectedClass"] = "item-selected";
                } else {
                    item["selectedClass"] = undefined;
                }
            });
        } else {
            this.something = null;
            this.items.forEach(item => {
                    item["selectedClass"] = undefined;
            });
        }

        return of(null);
    }
Run Code Online (Sandbox Code Playgroud)

小智 10

看看这个演示:https : //stackblitz.com/edit/angular-yjbpoq?file=src%2Fapp%2Fhello.component.ts

要点是您将一个新指令附加到您的列表和每个列表项:

<mat-list appScrollable ...>
  <mat-list-item appOffsetTop ...>
  ...
  </mat-list-item>
</mat-list>
Run Code Online (Sandbox Code Playgroud)

列表中的那个可以为列表设置scrollTop(或使用scrollTo,或其他):

@Directive({selector: '[appScrollable]'})
export class ScrollableDirective {
  constructor(private _el: ElementRef) {}
  set scrollTop(value: number) { this._el.nativeElement.scrollTop = value; }
}
Run Code Online (Sandbox Code Playgroud)

列表项上的一项可以报告它们的offsetTops:

@Directive({ selector: '[appOffsetTop]'})
export class OffsetTopDirective {
  constructor(private _el: ElementRef) { }
  get offsetTop(): number { return this._el.nativeElement.offsetTop; }
}
Run Code Online (Sandbox Code Playgroud)

在组件中通过@ViewChild和访问每种类型的指令@ViewChildren:

  @ViewChildren(OffsetTopDirective) listItems: QueryList<OffsetTopDirective>;
  @ViewChild(ScrollableDirective) list: ScrollableDirective;
Run Code Online (Sandbox Code Playgroud)

在AfterViewInit生命周期钩子中,将在项目列表中搜索与当前所选项目匹配的项目(此处随机设置以进行说明)。scrollTop然后将列表设置为该项目的offsetTop:

  // Inside your component
  selectedItem = Math.floor(Math.random() * 500);
  items = new Array(500).fill(0).map((_, i) => `Item ${i}`);

  ngAfterViewInit() {
    this.list.scrollTop = this.listItems.find((_, i) => i === this.selectedItem).offsetTop;
  }
Run Code Online (Sandbox Code Playgroud)


Jay*_*ase 6

您可以将指令方法与scrollIntoView一起使用:

@Directive({
  selector: '[appScrollIntoView]'
})
export class ScrollIntoViewDirective implements OnChanges {
  @Input() appScrollIntoView: boolean | undefined;

  constructor(
    @Inject(PLATFORM_ID) private platformId: any,
    private elementRef: ElementRef
  ) {}

  ngOnChanges(simpleChange: SimpleChanges) {
    if (isPlatformBrowser(this.platformId)) {
      if (coerceBooleanProperty(this.appScrollIntoView)) {
        (this.elementRef.nativeElement as HTMLInputElement).scrollIntoView({
          behavior: 'smooth',
          block: 'center'
        });
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

  <mat-list class="list" role="list">
    <mat-list-item
      class="list-item"
      [class.selected]="item === selectedItem"
      [appScrollIntoView]="item === selectedItem"
      *ngFor="let item of items"
      (click)="selectedItem = item"
      role="listitem"
      >{{ item.name }}</mat-list-item
    >
  </mat-list>
Run Code Online (Sandbox Code Playgroud)

堆栈闪电战

如果您使用材质选择列表,MatListOption有一个焦点方法,这是另一个选项。

@Directive({
  selector: 'mat-list-option[appScrollIntoView]'
})
export class ScrollIntoViewDirective implements OnChanges {
  @Input() appScrollIntoView: boolean | undefined;

  constructor(
    @Inject(PLATFORM_ID) private platformId: any,
    private elementRef: ElementRef,
    private matListOption: MatListOption
  ) {}

  ngOnChanges(simpleChange: SimpleChanges) {
    if (isPlatformBrowser(this.platformId)) {
      if (coerceBooleanProperty(this.appScrollIntoView)) {
        this.matListOption.focus();
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

  <mat-selection-list
    (selectionChange)="selectedItem = $event.option.value"
    class="list"
    [multiple]="false"
    role="list"
    #itemList
  >
    <mat-list-option
      class="list-item"
      [appScrollIntoView]="option.selected"
      *ngFor="let item of items"
      role="listitem"
      [selected]="item === selectedItem"
      [value]="item"
      #option
      >{{ item.name }}</mat-list-option
    >
  </mat-selection-list>
Run Code Online (Sandbox Code Playgroud)

堆栈闪电战