[英]How to display a preview value on mat-select Angular Material
[英]how to use scroll event in angular material mat select?
我有一个很大的列表,我想在用户向下滚动选择字段时加载它,但是如何在 mat-select 中获取滚动事件没有触发滚动事件的事件。
<mat-form-field>
<mat-select placeholder="Choose a Doctor" formControlName="selectedDoc" (change)="drSelected()">
<div *ngFor="let dr of doctors;let i = index" [matTooltip]="getDocDetail(i)" matTooltipPosition="right">
<mat-option (scroll)="docScroll()" [value]="dr">
{{dr.name}}
</mat-option>
</div>
</mat-select>
<mat-hint>List Of Doctor In Your city</mat-hint>
<mat-error *ngIf="selectedDoc.hasError('required')">Please Select A Dr</mat-error>
</mat-form-field>
(滚动)不起作用,因为 mat-select 没有任何滚动事件,我可以通过任何其他方式实现这一点,我想先显示 10 个项目,然后在用户滚动选项结束时填充其余项目。
查看我创建的Stackblitz 。
在您的组件,让MatSelect
通过ViewChild
访问其滚动面板。 然后向面板添加一个事件侦听器,当scrollTop
位置超过某个阈值时,它会重新加载医生并更新viewDoctors
数组。
allDoctors = ['doctor', 'doctor', ..., 'doctor'];
viewDoctors = this.allDoctors.slice(0, 10);
private readonly RELOAD_TOP_SCROLL_POSITION = 100;
@ViewChild('doctorSelect') selectElem: MatSelect;
ngOnInit() {
this.selectElem.onOpen.subscribe(() => this.registerPanelScrollEvent());
}
registerPanelScrollEvent() {
const panel = this.selectElem.panel.nativeElement;
panel.addEventListener('scroll', event => this.loadAllOnScroll(event));
}
loadAllOnScroll(event) {
if (event.target.scrollTop > this.RELOAD_TOP_SCROLL_POSITION) {
this.viewDoctors = this.allDoctors;
}
}
不要忘记将mat-select
分配给模板中的变量,以便您可以通过ViewChild
访问它:
<mat-form-field>
<mat-select placeholder="Choose a Doctor" #doctorSelect>
^^^^^^^^^^^^^
<mat-option *ngFor="let dr of viewDoctors;let i = index">
{{dr}}
</mat-option>
</mat-select>
</mat-form-field>
这只是一个非常基本的设置来说明这个想法。 您可能想要显示加载动画,清理事件侦听器,...
到目前为止, mat-select
组件的无限滚动仍然不可用,并保持为一个未解决的问题。 同时,看看ng-mat-select-infinite-scroll ,你可以用它来延迟加载你的数据。
import { MatFormFieldModule, MatSelectModule } from '@angular/material';
import {MatSelectInfiniteScrollModule} from 'ng-mat-select-infinite-scroll';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
MatFormFieldModule,
MatSelectModule,
MatSelectInfiniteScrollModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
组件
total = 100;
data = Array.from({length: this.total}).map((_, i) => `Option ${i}`);
limit = 10;
offset = 0;
options = new BehaviorSubject<string[]>([]);
options$: Observable<string[]>;
constructor() {
this.options$ = this.options.asObservable().pipe(
scan((acc, curr) => {
return [...acc, ...curr];
}, [])
);
}
ngOnInit() {
this.getNextBatch();
}
getNextBatch() {
const result = this.data.slice(this.offset, this.offset + this.limit);
this.options.next(result);
this.offset += this.limit;
}
模板
<mat-form-field appearance="outline">
<mat-label>Select</mat-label>
<mat-select msInfiniteScroll (infiniteScroll)="getNextBatch()" [complete]="offset === data.length">
<mat-option *ngFor="let option of options$ | async" [value]="option">{{option}}</mat-option>
</mat-select>
</mat-form-field>
这是一个工作示例
基于 Kim 的回答,滚动高度和顶部可用于检测用户何时到达下拉列表的底部(请参阅此 SO 问题)
我还更新了逻辑以在滚动时加载接下来的 10 条记录,以防整个数据集太大而无法一次性加载。
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatSelect } from '@angular/material/select';
@Component({
selector: 'toolbar-multirow-example',
templateUrl: 'toolbar-multirow-example.html',
styleUrls: ['toolbar-multirow-example.css']
})
export class ToolbarMultirowExample implements OnInit {
allDoctors = Array.from(new Array(3000).keys()).map(i => 'Doctor ' + i);
viewDoctors = this.allDoctors.slice(0, 10);
viewIndex = 0;
windowSize = 10;
private readonly PIXEL_TOLERANCE = 3.0;
@ViewChild('doctorSelect') selectElem: MatSelect;
ngOnInit() {
this.selectElem.openedChange.subscribe(() =>
this.registerPanelScrollEvent()
);
}
registerPanelScrollEvent() {
const panel = this.selectElem.panel.nativeElement;
panel.addEventListener('scroll', event => this.loadNextOnScroll(event));
}
loadNextOnScroll(event) {
if (this.hasScrolledToBottom(event.target)) {
console.log('Scrolled to bottom');
this.viewIndex += this.windowSize;
this.viewDoctors = this.allDoctors.slice(0,this.viewIndex);
}
}
private hasScrolledToBottom(target): boolean {
return Math.abs(target.scrollHeight - target.scrollTop - target.clientHeight) < this.PIXEL_TOLERANCE;
}
reset() {
this.viewDoctors = this.allDoctors.slice(0, 10);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.