Проверьте это демо: https://stackblitz.com/edit/angular-yjbpoq?file=src%2Fapp%2Fhello.component.ts
Суть в том, что вы присоединяете новую директиву к вашему списку и к каждому из элементов списка:
<mat-list appScrollable ...>
<mat-list-item appOffsetTop ...>
...
</mat-list-item>
</mat-list>
Один из списка может установить scrollTop
(или использовать scrollTo
, или что-то еще) для списка:
@Directive({selector: '[appScrollable]'})
export class ScrollableDirective {
constructor(private _el: ElementRef) {}
set scrollTop(value: number) { this._el.nativeElement.scrollTop = value; }
}
А тот, кто находится в списке, может сообщить свои offsetTop
s:
@Directive({ selector: '[appOffsetTop]'})
export class OffsetTopDirective {
constructor(private _el: ElementRef) { }
get offsetTop(): number { return this._el.nativeElement.offsetTop; }
}
Каждый тип директивы доступен в компоненте через @ViewChild
и @ViewChildren
:
@ViewChildren(OffsetTopDirective) listItems: QueryList<OffsetTopDirective>;
@ViewChild(ScrollableDirective) list: ScrollableDirective;
В хуке жизненного цикла 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;
}