我有两套代码可以用,但我都不能按我想要的方式工作。所以我希望有一些概念上的见解。
我有一个从API获取服务的城市。此服务自动完成筛选结果。当我使用
form builder
,我无法获取要筛选的数据,因为它没有执行
fromLatestWith
.
我正在使用
从最近的
使用两个观测数据
valueChange
以及为城市带来的服务。它在我使用时起作用
formControl
但不能
formBuilder
.
当我不使用
弗拉斯特
我可以让服务和自动完成功能工作,但是,由于服务首先加载,所以我必须在自动完成下拉列表显示之前键入。
理想情况下我想用
formbuilder
并拥有
自动完成下拉列表
初始化时。我错过了什么?
以下是两个实例的副本:
//using formBuilder with latestWith lets me see valueChange but doesnt
//load cities if I don't use formBuilder and use formControl it works
import { CityService } from "../services/city-list.service";
import { Component, OnInit, OnDestroy } from "@angular/core";
import { City } from "../models/city";
import { Subscription, Observable } from "rxjs";
import {
map,
filter,
startWith,
withLatestFrom,
debounceTime
} from "rxjs/operators";
import {
FormGroup,
FormControl,
FormBuilder,
Validators,
NgForm,
Form
} from "@angular/forms";
@Component({
selector: "app-city-list",
templateUrl: "./city-list.component.html",
styleUrls: ["./city-list.component.css"]
})
export class CityListComponent implements OnInit {
cities: Observable<City[]>;
destinationCitySub: Observable<City[]>;
originCitySub: Observable<City[]>;
instantFlightForm: FormGroup;
constructor(public cityService: CityService, private fb: FormBuilder) {
}
ngOnInit() {
this.instantFlightForm = this.fb.group({
destinationCity: [""],
originCity: ["", Validators.required],
startDate: []
});
this.cityService.getCities();
this.cities = this.cityService.getCityUpdateListener();
this.destinationCitySub = this.valueChange('destinationCity');
}
private valueChange(string) {
console.log(string);
return this.instantFlightForm.get(string).valueChanges.pipe(
withLatestFrom(this.cities),
debounceTime(100),
map(([term, city]) => {
console.log(term);
return this._filter(term, city);
})
);
}
private _filter(first, second): City[] {
const filterValue = first.toLowerCase();
return second.filter(option =>
option.name.toLowerCase().includes(filterValue)
);
}
onInstantSearch(form: FormGroup) {
console.log(form.value);
}
}
<mat-card>
<form [formGroup]="instantFlightForm" (submit)="onInstantSearch(instantFlightForm)">
<mat-form-field>
<input type="text" id="destinationCity" name="destinationCity" matInput formControlName="destinationCity" [matAutocomplete]="autoDestination">
<mat-autocomplete #autoDestination="matAutocomplete">
<mat-option *ngFor="let c of destinationCitySub|async" [value]="c.code">
{{c.name}} - {{c.code}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<input type="text" id="originCity" name="originCity" matInput formControlName="originCity" [matAutocomplete]="autoOrigin">
<mat-autocomplete #autoOrigin="matAutocomplete">
<mat-option *ngFor="let c of originCitySub|async" [value]="c">
{{c}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<input matInput id="startDate" name="startDate" formControlName="startDate" [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
<button mat-raised-button type="submit" color="accent">Search</button>
</form>
</mat-card>
//using it without latestWith - lets me autocomplete but requires
//typing first
import { CityService } from "../services/city-list.service";
import { Component, OnInit, OnDestroy } from "@angular/core";
import { City } from "../models/city";
import { Subscription, Observable } from "rxjs";
import {
map,
filter,
startWith,
withLatestFrom,
debounceTime
} from "rxjs/operators";
import {
FormGroup,
FormControl,
FormBuilder,
Validators,
NgForm,
Form
} from "@angular/forms";
@Component({
selector: "app-city-list",
templateUrl: "./city-list.component.html",
styleUrls: ["./city-list.component.css"]
})
export class CityListComponent implements OnInit {
cities: City[];
citySub: Subscription;
destinationCitySub: Observable<City[]>;
originCitySub: Observable<City[]>;
instantFlightForm: FormGroup;
constructor(public cityService: CityService, private fb: FormBuilder) {
}
ngOnInit() {
this.instantFlightForm = this.fb.group({
destinationCity: [""],
originCity: ["", Validators.required],
startDate: []
});
this.cityService.getCities();
this.citySub = this.cityService.getCityUpdateListener().subscribe(c=>this.cities=c);
this.destinationCitySub = this.valueChange('destinationCity');
}
private valueChange(string) {
return this.instantFlightForm.get(string).valueChanges.pipe(
// withLatestFrom(this.cities),
debounceTime(100),
map((term) => {
console.log(term);
return this._filter(term);
})
);
}
private _filter(term): City[] {
const filterValue = term.toLowerCase();
return this.cities.filter(option =>
option.name.toLowerCase().includes(filterValue)
);
}
onInstantSearch(form: FormGroup) {
console.log(form.value);
}
}