我有一个包含多个元素的Angular Material列表,可以在其中选择一个元素。
当我加载该列表时,我想将列表向上滚动到所选元素,以使其更加可见。有什么选择吗?
我当时正在考虑类似ngOnInit来检查是否选中了该项目,但是我真的不知道如何将列表向上滚动到该项目。
注意:不是整个页面都应该滚动,只滚动列表中的元素。
component.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>
component.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);
}
答案 0 :(得分:1)
您可以在 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'
});
}
}
}
}
用法:
<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>
如果您使用材料选择列表,MatListOption 有一个 focus 方法,这是另一种选择。
@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();
}
}
}
}
用法:
<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>
答案 1 :(得分:0)
几乎没有代码,但是您可以给所有元素一个ID,也许像
然后使用ngOnInit
检查您选择的元素,使用document.getElementById('listelement'+elementid)
选择DOM元素并将其滚动到视图中。
经典的JS方法是element.scrollIntoView();
答案 2 :(得分:0)
查看此演示: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
:
@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;
}