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)
您可以将指令方法与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)