angular - 填充数组并使其可使用 Angular Material 过滤
问题描述
我想在我的 Angular 应用程序启动时填充一个数组并将其用于 Material Autocomplete。我可以从我的 PHP 后端接收 JSON。在 ngOnInit 中,我什至可以将其提供给数组并将其注销。但是后来我的数组仍然未定义。我应该怎样做才能让内容最终出现在我的选项列表中?
app.component.html:
<form class="example-form">
<mat-form-field class="example-full-width">
<input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">
{{option}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
app.component.ts:
import {Component, OnInit, AfterViewInit} from '@angular/core';
import {FormControl} from '@angular/forms';
import {Observable} from 'rxjs';
import {map, startWith, takeUntil, switchMap} from 'rxjs/operators';
import { ServerService } from './server.service';
/**
* @title Filter autocomplete
*/
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css'],
})
export class AppComponent implements OnInit {
myControl = new FormControl();
megyek: Observable<string[]>;
filteredOptions: Observable<string[]>;
constructor(private serverService: ServerService) { }
ngOnInit() {
// don't manually subscribe!
this.megyek = this.serverService.getMegyek();
// use switchmap, if user types fast
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
switchMap(value => this._filter(value))
);
}
private _filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.megyek
.filter(option => option.toLowerCase().includes(filterValue));
}
}
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { ServerService } from './server.service';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import {
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatRippleModule,
MatAutocompleteModule,
} from '@angular/material';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
@NgModule({
exports: [
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatRippleModule,
MatAutocompleteModule,
ReactiveFormsModule,
BrowserAnimationsModule,
FormsModule,
HttpModule
],
declarations: [],
imports: []
})
export class MaterialModule {}
@NgModule({
declarations: [
AppComponent
],
imports: [
MaterialModule,
BrowserModule,
],
providers: [ServerService],
bootstrap: [
AppComponent,
],
schemas: [],
})
export class AppModule { }
服务器.service.ts
import {throwError as observableThrowError, Observable } from 'rxjs';
import {catchError, map} from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';
@Injectable()
export class ServerService {
constructor(private http: Http) {}
storeServers(servers: any[]) {
const headers = new Headers({'Content-Type': 'application/json'});
// return this.http.post('https://udemy-ng-http.firebaseio.com/data.json',
// servers,
// {headers: headers});
return this.http.put('https://udemy-ng-http.firebaseio.com/data.json',
servers,
{headers: headers});
}
getMegyek() {
return this.http.get('http://localhost/Varosok/Controller/ControllerCity.php?content=megyek').pipe(
map(
(response: Response) => {
console.log(response);
const data = response.json();
/*for (const megye of data) {
megye.trim();
}*/
return data;
}
),
catchError(
(error: Response) => {
console.log(error);
return observableThrowError('Something went wrong');
}
), );
}
getAppName() {
return this.http.get('https://udemy-ng-http.firebaseio.com/appName.json').pipe(
map(
(response: Response) => {
return response.json();
}
));
}
}
解决方案
请记住,您的填充请求megyek
是异步的。所以当AfterViewInit
被执行时,megyek
没有值(还)但是是undefined
,因此它抛出错误。保持megyek
Observable 并且不要使用AfterViewInit
. 所以试试:
myControl = new FormControl();
megyek: Observable<string[]>;
filteredOptions: Observable<string[]>;
constructor(private serverService: ServerService) { }
ngOnInit() {
// don't manually subscribe!
this.megyek = this.serverService.getMegyek();
// use switchmap, if user types fast
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
switchMap(value => this._filter(value))
);
}
同样在您的过滤器中,您需要使用 map 来访问数组中的每个字段,而且我将其更改为 rxjs 6,pipe
看起来您正在使用它。
private _filter(value: string): Observable<string[]> {
return this.megyek.pipe(
map(options => options.filter(option => option.toLowerCase().includes(value)))
)
}
演示:StackBlitz
推荐阅读
- python - 如何在 openpyxl 中启用迭代计算?
- google-analytics - Google Analytics 4 购买事件更新
- php - 如何在 PHP 中处理一个页面上的两个表单
- c# - 错误:未经身份验证,必须通过身份验证才能使用“/drive”语法 - 使用 rest api 获取项目时(图表)
- java - Infinispan Junit 5:CacheConfigurationException:ISPN000501:无法持久缓存配置,因为全局状态已禁用
- python - Spyder 无法显示您尝试查看的变量
- c# - Mapster,尝试映射到具有许多没有默认构造函数的类的字段并失败
- java - “E/android.hardware.audio@6.0-impl.ranchu: WriteThread::doWriteImpl:226: pcm_write failed with Operation not allowed”在 Android Studio
- python - 从 Excel 文件中查找 Python 中的中位数
- cassandra - Cassandra:删除整个分区会创建墓碑吗?