1

我有以下要求父组件有一个子垫自动完成组件,它在每个用户输入(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 演示

但我面临版本依赖问题

4

0 回答 0