html - Angular 过滤器和绑定 (ngModelChange)
我正在做酒店项目。我有一个预订界面。在这里我会询问酒店名称、地区名称、入住和退房日期、成人和儿童人数。当必要的信息输入完成后,点击搜索按钮时,我会根据这些值进行过滤。我使用 (NgModelChange) 方法将日期过滤器与 HTML 连接起来了,但我没能正确将 HTML 与酒店和地区的方法连接起来。我做了一个实验性的过滤器,但得到了错误的结果。我不知道自己错在哪里。我该如何修复这个问题?
.html
<form [formGroup]="form">
<mat-form-field>
<label>Which Hotel?</label>
<input type="text" matInput [matAutocomplete]="name" formControlName="name" (change)="changeHotel()" />
<mat-autocomplete #name="matAutocomplete">
<mat-option *ngFor="let hotel of filteredHotels | async" [value]="hotel">
{{hotel}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<label>Which Region?</label>
<input type="text" matInput [matAutocomplete]="region" formControlName="region" (change)="changeRegion()" />
<mat-autocomplete #region="matAutocomplete">
<mat-option *ngFor="let region of filteredRegions | async" [value]="region">
{{region}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<label>Entry Date?</label>
<input matInput [matDatepicker]="mdpStartDate" formControlName="startDate" (ngModelChange)="changeDate()">
<mat-datepicker-toggle matSuffix [for]="mdpStartDate"></mat-datepicker-toggle>
<mat-datepicker #mdpStartDate></mat-datepicker>
</mat-form-field>
<mat-form-field>
<label>Pay Date?</label>
<input matInput [matDatepicker]="mdpEndDate" formControlName="endDate" (ngModelChange)="changeDate()">
<mat-datepicker-toggle matSuffix [for]="mdpEndDate"></mat-datepicker-toggle>
<mat-datepicker #mdpEndDate></mat-datepicker>
</mat-form-field>
<br />
<mat-form-field>
<label>Adult Number?</label>
<input type="number" min="1" matInput formControlName="adult" (ngModelChange)="filterAge()">
</mat-form-field>
<mat-form-field>
<label>Chd Number?</label>
<input type="number" min="0" max="3" value="0" matInput formControlName="chd" (ngModelChange)="filterAge()">
</mat-form-field>
<button type="button" class="btn btn-success" (click)="search()">Search</button>
.ts
form = new FormGroup({
name: new FormControl(''),
region: new FormControl(''),
adult: new FormControl(1),
chd: new FormControl(0),
startDate: new FormControl(),
endDate: new FormControl(),
});
filtered: any[];
showList = false;
name = '';
regions: string[];
hotels: Hotel[] = [];
filteredHotels: Observable<string[]>;
filteredRegions: Observable<string[]>;
ngOnInit() {
this.regions = this.hotels.reduce((arr: string[], current) => {
if (!arr.includes(current.regionName)) {
arr.push(current.regionName);
}
return arr;
}, []);
this.filteredHotels = this.form.get("name").valueChanges
.pipe(
startWith(''),
map(v => {
return this.filterHotels(v)
})
);
this.filteredRegions = this.form.get("region").valueChanges
.pipe(
startWith(''),
map(value => this.filterRegions(value).map(h => h.regionName))
);
this.form.get("adult").valueChanges.
subscribe(v => {
this.adult = new Array(v).map(e => new Object)
});
this.form.get("chd").valueChanges
.subscribe(v => {
this.children = new Array(v).map(e => new Object)
});
this.hotelservice.getHotels().subscribe(
data => {
this.hotels = data;
this.dsHotels.data = data;
this.dsHotels.paginator = this.paginator;
},
err => {
console.error("Hata oluştu: ", err);
}
);
}
private filterHotels(value: string): string[] {
const name = value.toLowerCase();
return this.hotels
.map(x => x.hotelName)
.filter(option => option.toLowerCase().includes(name));
}
private filterRegions(value: string): Hotel[] {
const region = value.toLowerCase();
return this.hotels
.filter(hotel => hotel.regionName.toLowerCase().includes(region));
}
private isEqual(date1: Date, date2: Date) {
return date1.getDate() == date2.getDate() && date1.getMonth() == date2.getMonth() && date1.getFullYear() == date2.getFullYear();
}
private isDataEqualToDate(value1: any, date2: Date) {
if (value1 == null) return true;
return this.isEqual(new Date(value1), date2);
}
private getFilteredDate(): Hotel[] {
return this.hotels.filter(
x => this.isDataEqualToDate(this.form.get("startDate").value, new Date(x.checkInDate))
&& this.isDataEqualToDate(this.form.get("endDate").value, new Date(x.payDate))
);
}
changeHotel() {
this.dsHotels.data = this.filterHotels("value");
}
changeRegion() {
this.dsHotels.data = this.filterRegions("value");
}
changeDate() {
this.dsHotels.data = this.getFilteredDate();
}
filterAge() {
//this.dsHotels.data = this.hotels.filter(x => x.numberOfAd == this.form.get("adult").value && x.numberOfChd == this.form.get("chd").value);
this.dsHotels.data = this.hotels.filter(x => x.numberOfAd == x.numberOfChd);
}
search() {
this.showList = true;
this.filterHotels("");
this.filterRegions("");
this.changeDate();
}
答案#1
由于您使用响应式表单创建了表单,因此可以在模板中从事件绑定切换
< ... (change)="changeHotel()"
< ... (ngModelChange)="changeDate()">
在课堂上做这件事。
ngOnInit() {
// ... initial logic
this.form.get('name').valueChanges.subscribe(this.changeHotel.bind(this))
this.form.get('region').valueChanges.subscribe(this.changeRegion.bind(this))
this.form.get('startDate').valueChanges.subscribe(this.changeDate.bind(this))
this.form.get('endDate').valueChanges.subscribe(this.changeDate.bind(this))
this.form.get('adult').valueChanges.subscribe(this.filterAge.bind(this))
this.form.get('chd').valueChanges.subscribe(this.filterAge.bind(this))
}
像 FormGroup 和 FormControl 这样的响应式表单实例有一个 valueChanges 方法,它返回一个可观察对象,发出最新的值。因此,你可以订阅 valueChanges 来更新实例变量或执行操作。
源
