我有一个带有mat-autocomplete元素的应用程序,其中有城市作为选项。城市来自数据库。有一个添加输入元素的按钮。这是通过使div元素具有* ngFor属性来实现的,该属性会循环访问component.ts文件中的属性。单击添加按钮时,会将元素添加到属性中,并因此添加输入。但是,当我在第一个输入中键入城市名称,然后尝试添加输入元素时,我得到了ExpressionChangedAfterItHaHasBeenCheckedError。
我发现很多人都遇到了这个错误,但是我已经尝试了所有给定的解决方案,但是其中的一个似乎都不起作用。喜欢:
startWith(''),
delay(0),
map(value => this._filter(value))
);
ngAfterViewInit(){
this.cd.detectChanges();
}
var request = new CityCreationRequestModel();
request.name = "";
Promise.resolve(null).then(() => this.reportGroupCreationRequest.cityReportGroups.push(request));
并尝试超时。
这是我的html文件:
<div class="container">
<mat-card>
<mat-card-header>
<mat-card-title>Voeg een reportgroep toe</mat-card-title>
<mat-card-subtitle>Geef emailadressen op die verbonden worden met de rapporten van bepaalde steden</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<form (ngSubmit)="onSubmit()" #addReportGroup="ngForm" *ngIf="!isLoading">
<div *ngFor="let city of reportGroupCreationRequest.cityReportGroups" class="form-row">
<mat-form-field>
<input placeholder="Stad" required [(ngModel)]="city.name" type="text" matInput [formControl]="myControl" [matAutocomplete]="auto" name="cityInput">
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
<mat-option *ngFor="let cityName of filteredOptions | async" [value]="cityName">
{{ cityName }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>
<button mat-raised-button (click)="addCity()">Voeg een stad toe</button>
<div class="form-row">
<button mat-raised-button type="submit" [disabled]="!addReportGroup.valid" class="submitButton">Opslagen</button>
</div>
</form>
<mat-spinner [style.display]="isLoading ? 'block' : 'none'"></mat-spinner>
</mat-card-content>
</mat-card>
这是我的.ts文件:
如果是mat-autocomplete元素,则为过滤器
export class AddReportGroupComponent implements OnInit {
myControl = new FormControl();
filteredOptions: Observable<string[]>;
public reportGroupCreationRequest: ReportGroupCreationRequestModel = new ReportGroupCreationRequestModel();
public cities: Array<CityResponseModel>;
public cityNames: Array<string>;
private isLoading: boolean;
constructor(private reportGroupService: ReportGroupService,
private cd: ChangeDetectorRef) {
}
ngOnInit() {
this.isLoading = true;
this.reportGroupService.getCities().subscribe(result => {
this.cities = result;
this.cities.sort((a,b) => a.name.localeCompare(b.name));
this.cityNames = this.cities.map(c=>c.name);
}).add(()=> {
this.isLoading = false;
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
delay(0),
map(value => this._filter(value))
);
});
this.reportGroupCreationRequest.cityReportGroups.push(new CityCreationRequestModel());
this.reportGroupCreationRequest.emailReportGroups.push(new EmailCreationRequestModel());
}
//doesn't seem to do anything
ngAfterViewInit(){
this.cd.detectChanges();
}
private _filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.cityNames.filter(cn => cn.toLowerCase().indexOf(filterValue) === 0);
}
addCity(){
var request = new CityCreationRequestModel();
request.name = "";
Promise.resolve(null).then(() => this.reportGroupCreationRequest.cityReportGroups.push(request));
}
这些是我使用的模型:
export class ReportGroupCreationRequestModel {
public cityReportGroups: Array<CityCreationRequestModel> = new Array<CityCreationRequestModel>();
public emailReportGroups: Array<EmailCreationRequestModel> = new Array<EmailCreationRequestModel>();
}
export class CityCreationRequestModel {
public name: string;
}
预先感谢
我为遇到的问题找到了解决方案:
我同时使用了[[ngModel)]和[FormsControl],显然[[ngModel)]是问题的一部分,所以我只使用了[FormsControl],错误消失了。
addCity(){
this.reportGroupCreationRequest.cityReportGroups[this.reportGroupCreationRequest.cityReportGroups.length - 1].name = this.myControl.value;
Promise.resolve(null).then(() => this.reportGroupCreationRequest.cityReportGroups.push(new CityCreationRequestModel()));
}
<div *ngFor="let city of reportGroupCreationRequest.cityReportGroups" class="form-row">
<mat-form-field>
<input placeholder="Stad" required type="text" matInput [formControl]="myControl" [matAutocomplete]="auto" name="cityInput">
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
<mat-option *ngFor="let cityName of filteredOptions | async" [value]="cityName">
{{ cityName }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>