我的网站上有一个自动完成搜索栏。它是用 Angular 7 构建的,信息来 self 的 Firestore 数据库。目前,当用户键入时,搜索栏不会过滤选项。 onLoad() 函数应该对我的 Schools
集合进行一次提取,并在用户输入时筛选该集合。
搜索栏代码
<form>
<mat-form-field style="width: 50vw; max-width: 400px;" appearance="outline">
<input matInput placeholder="Search schools..." aria-label="School" [matAutocomplete]="auto" #schoolInput [(ngModel)]="searchModel" (keyup.enter)="searchButton(schoolInput.value)" name="inputField" id="searchInput">
<mat-icon class="searchIcon" matSuffix style="color: #6336c6;" (click)="searchButton(schoolInput.value)">search</mat-icon>
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let school of schools | async" [value]="school.name">
<span class="ui tiny header">{{ school.name }}</span>
<span *ngIf="school.country == 'United States'; then withState else withoutState"></span>
<ng-template #withState><small> {{school.city}}, {{school.state}}</small></ng-template>
<ng-template #withoutState><small> {{school.city}}, {{school.country}}</small></ng-template>
</mat-option>
<mat-option *ngIf="user" (click)="openDialogAddSchool()" style="font-style: italic; padding-bottom: 4px; margin-bottom: 12px;">
<button class="ui basic fluid violet button" style="margin-top:6px;"><i class="plus icon"></i>Add school</button>
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
到目前为止的 TS 代码
fetchSchools(){
this.schoolsCollection = this.afs.collection('Schools', ref => {
return ref.orderBy('name');
});
this.schools = this.schoolsCollection.valueChanges();
console.log('Retreived schools:');
console.log(this.schools);
}
回应 检索学校:
page-home.component.ts:308 Observable {_isScalar: false, source: Observable, operator: MapOperator}
最佳答案
我会推荐一个服务,通常我们使用一个服务来处理 http 调用,在本例中是 firebase 查询。因此,我将创建服务,创建一个 schools
变量,如果它有值(value),则返回它的可观察值,或者然后从 firebase 查询返回结果,除非您想始终查询数据库,但这会变得非常昂贵。
schools = [];
fetchSchools() {
if (this.schools && this.schools.length) {
return of(this.schools)
} else {
return this.afs.collection('Schools', ref => {
return ref.orderBy('name')
}).valueChanges().pipe(
tap((schools) => this.schools = schools)
);
}
}
组件将订阅此数据,并在数据被过滤后将数据分配给可观察对象。我喜欢添加一个 debounceTime
:
filterSchools() {
this.schoolsObs = this.myService.fetchSchools().pipe(
debounceTime(300),
map((data) => this.performFilter(data))
)
}
然后您可以选择如何完成过滤...使用startsWith
、includes
(??)。还要选择您想要过滤的 Prop 。我的示例如下所示:
performFilter(schoolsObs) {
return schoolsObs.filter((x) => {
// filter by what prop you want
return x.name.toLowerCase().startsWith(this.searchModel.trim().toLowerCase())
})
}
最后对于模板,我会监听用户的输入
:
<input
matInput
[matAutocomplete]="auto"
(input)="filterSchools()"
[(ngModel)]="searchModel"
>
演示: StackBlitz
关于Angular + Firestore 自动完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57564756/