Angular - 在 mat-select 中实现 NgxMatSelectSearch
Angular - Implement NgxMatSelectSearch in mat-select
我正在尝试使用 mat-select 中的搜索框,该搜索框仅在使用默认加载的数据时才能正常工作。我想使用来自 api 的数据。但是不能正常工作,加载页面时数据不显示在mat-select中,但是当焦点出现在mat-select标签中时显示。
我有一个模型,我在其中使用来自测试的数据 API
export interface DataModel {
id: number;
title: string;
userId: number;
}
export const DataModels: DataModel[] = [
{ id: 1, title: 'Option A', userId: 23 },
{ id: 2, title: 'Option B', userId: 24 },
{ id: 3, title: 'Option C', userId: 25 },
{ id: 4, title: 'Option D', userId: 26 }
];
我打电话的服务
@Injectable()
export class DataloadService {
constructor(private http: HttpClient) {}
LoadData(): Observable<any> {
return this.http.get('https://jsonplaceholder.typicode.com/albums');
}
}
执行搜索过滤器和设置控件的组件。按照文档 NgxMatSelectSearch
constructor(private service: DataloadService) {}
dataModel: DataModel[] = []; //DataModels
dataCtrl: FormControl = new FormControl();
dataFilterCtrl: FormControl = new FormControl();
filteredData: ReplaySubject<DataModel[]> = new ReplaySubject<DataModel[]>(1);
@ViewChild('singleSelect', { static: true }) singleSelect: MatSelect;
_onDestroy = new Subject<void>();
ngOnInit() {
this.load();
this.filteredData.next(this.dataModel.slice());
this.dataFilterCtrl.valueChanges
.pipe(takeUntil(this._onDestroy))
.subscribe(() => {
this.filterData();
});
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
filterData() {
if (!this.dataModel) {
return;
}
let search = this.dataFilterCtrl.value;
if (!search) {
this.filteredData.next(this.dataModel.slice());
return;
} else {
search = search.toLowerCase();
}
this.filteredData.next(
this.dataModel.filter(
(x: any) => x.title.toLowerCase().indexOf(search) > -1
)
);
}
load() {
return this.service.LoadData().subscribe(res => {
this.dataModel = res;
});
}
还有 HTML
<mat-card>
<mat-toolbar>Demo</mat-toolbar><br />
<mat-card-content>
<mat-select [formControl]="dataCtrl" placeholder="Data" #singleSelect>
<mat-option>
<ngx-mat-select-search
[formControl]="dataFilterCtrl"
></ngx-mat-select-search>
</mat-option>
<mat-option *ngFor="let x of filteredData | async" [value]="x.id">
{{x.title}}
</mat-option>
</mat-select>
</mat-card-content>
</mat-card>
如果我使用模型中默认的数据来模拟使用“dataModels”的过程
dataModel: DataModel[] = []; //DataModels
而不是将其初始化为空。它工作正常,但如果我根据对 API 的请求加载数据,就会出现焦点发生后未加载数据的问题。
我在 Stackblitz 中的演示:Demo Stackblitz
你应该添加这一行
this.filteredData.next(this.dataModel.slice());
进入 this.service.LoadData()
的 subscribe
事件,因为它是异步的。这样当返回响应结果时,filteredData
与响应结果绑定。
load() {
return this.service.LoadData().subscribe(res => {
this.dataModel = res;
this.filteredData.next(this.dataModel.slice());
});
}
我正在尝试使用 mat-select 中的搜索框,该搜索框仅在使用默认加载的数据时才能正常工作。我想使用来自 api 的数据。但是不能正常工作,加载页面时数据不显示在mat-select中,但是当焦点出现在mat-select标签中时显示。
我有一个模型,我在其中使用来自测试的数据 API
export interface DataModel {
id: number;
title: string;
userId: number;
}
export const DataModels: DataModel[] = [
{ id: 1, title: 'Option A', userId: 23 },
{ id: 2, title: 'Option B', userId: 24 },
{ id: 3, title: 'Option C', userId: 25 },
{ id: 4, title: 'Option D', userId: 26 }
];
我打电话的服务
@Injectable()
export class DataloadService {
constructor(private http: HttpClient) {}
LoadData(): Observable<any> {
return this.http.get('https://jsonplaceholder.typicode.com/albums');
}
}
执行搜索过滤器和设置控件的组件。按照文档 NgxMatSelectSearch
constructor(private service: DataloadService) {}
dataModel: DataModel[] = []; //DataModels
dataCtrl: FormControl = new FormControl();
dataFilterCtrl: FormControl = new FormControl();
filteredData: ReplaySubject<DataModel[]> = new ReplaySubject<DataModel[]>(1);
@ViewChild('singleSelect', { static: true }) singleSelect: MatSelect;
_onDestroy = new Subject<void>();
ngOnInit() {
this.load();
this.filteredData.next(this.dataModel.slice());
this.dataFilterCtrl.valueChanges
.pipe(takeUntil(this._onDestroy))
.subscribe(() => {
this.filterData();
});
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
filterData() {
if (!this.dataModel) {
return;
}
let search = this.dataFilterCtrl.value;
if (!search) {
this.filteredData.next(this.dataModel.slice());
return;
} else {
search = search.toLowerCase();
}
this.filteredData.next(
this.dataModel.filter(
(x: any) => x.title.toLowerCase().indexOf(search) > -1
)
);
}
load() {
return this.service.LoadData().subscribe(res => {
this.dataModel = res;
});
}
还有 HTML
<mat-card>
<mat-toolbar>Demo</mat-toolbar><br />
<mat-card-content>
<mat-select [formControl]="dataCtrl" placeholder="Data" #singleSelect>
<mat-option>
<ngx-mat-select-search
[formControl]="dataFilterCtrl"
></ngx-mat-select-search>
</mat-option>
<mat-option *ngFor="let x of filteredData | async" [value]="x.id">
{{x.title}}
</mat-option>
</mat-select>
</mat-card-content>
</mat-card>
如果我使用模型中默认的数据来模拟使用“dataModels”的过程
dataModel: DataModel[] = []; //DataModels
而不是将其初始化为空。它工作正常,但如果我根据对 API 的请求加载数据,就会出现焦点发生后未加载数据的问题。
我在 Stackblitz 中的演示:Demo Stackblitz
你应该添加这一行
this.filteredData.next(this.dataModel.slice());
进入 this.service.LoadData()
的 subscribe
事件,因为它是异步的。这样当返回响应结果时,filteredData
与响应结果绑定。
load() {
return this.service.LoadData().subscribe(res => {
this.dataModel = res;
this.filteredData.next(this.dataModel.slice());
});
}