我有以下要求父组件有一个子垫自动完成组件,它在每个用户输入(500 毫秒的去抖动)上从服务器(json 文件)获取数据。我设法将数据从子窗体控件发送到父窗体控件,但是在为子组件设置默认值时遇到问题,因为-子组件中的数据尚不存在(它将在用户开始键入时填充)-要求需要获取出于性能考虑,来自服务器的数据,因为列表很大。3000条记录承载子组件的主机组件
主机 [App.Component]
@Component({
selector: 'app-root',
template: `
<div style="margin: 0 auto; width: 350px">
<form [formGroup]="form" *ngIf="form">
<legend>Reactive Forms</legend>
<app-country-autocomplete
formControlName="countryId">
</app-country-autocomplete>
<p>form value: {{form.value | json}}</p>
</form>
</div>`
})
export class AppComponent {
form: FormGroup;
constructor(fb: FormBuilder) {
this.form = fb.group({
// let's say that 213 is the value i would like to assign to control
countryId: new FormControl(213)
});
}
子 [CountryautocompleteComponent]
@Component({
selector: 'app-country-autocomplete',
template: `
<mat-form-field style="width: 100%">
<input type="text" matInput
[formControl]="countryControl"
[matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn"
(optionSelected)='onSelectionChanged($event)'>
<mat-option *ngFor="let country of countries | async" [value]="country">
{{ country.name}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CountryAutocompleteComponent),
multi: true
}]
})
export class CountryAutocompleteComponent implements OnInit, ControlValueAccessor {
countries: Observable<Country[]>;
countryControl = new FormControl();
// call when the value changes
onChange: (val: number) => void;
// we will call for any user action with the control
onTouched: () => void;
constructor(private service: CountryService) {
}
ngOnInit() {
this.countries = this.countryControl.valueChanges
.pipe(
startWith(''),
debounceTime(500),
distinctUntilChanged(),
switchMap((term: string) => this.service.search(term)
));
}
onSelectionChanged(event) {
this.value = +event.option.value.id;
}
private _value = 0;
get value() {
return this._value;
}
// set a new value and report this form
set value(value: number) {
this._value = value;
if (this.onChange) {
this.onChange(value);
}
}
// response to the host element click, we tell the form that the control was "touched"
@HostListener('click') click() {
if (this.onTouched) {
this.onTouched();
}
}
// the form will call if the value has changed externally
writeValue(obj: any): void {
this.value = +obj;
}
// save callback for changes
registerOnChange(fn: any): void {
this.onChange = fn;
}
// save callback for "touches"
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
displayFn(country: Country): string {
return country && country.name ? `${country.name}` : '';
}
国家.service.ts
@Injectable({
providedIn: 'root',
})
export class CountryService {
constructor(private http: HttpClient) { }
search(query: string) {
return this.http.get('assets/countries.json')
.pipe(map((x: Country[]) => x.filter(l =>
l.name.toLocaleLowerCase().includes(query.toString().toLocaleLowerCase()))));
}
}
国家.ts
export class Country {
id: number;
name: string;
}
国家.json
[
{
"name": "Afghanistan",
"id": 93
},
{
"name": "Albania",
"id": 355
},
{
"name": "Algeria",
"id": 213
},
{
"name": "American Samoa",
"id": 1684
}
]
我的问题是:
1)如何设置从主机到子组件的值,其中数据来自服务器但尚未出现?如果这不合逻辑,还有什么替代方法,因为我想避免在子组件中填充保留列表,并且我想根据用户输入返回一个子集。
我还准备了一个stackblitz 演示
但我面临版本依赖问题