Угловой элемент формы в отдельном компоненте дает ошибку FormGroup - PullRequest
0 голосов
/ 28 августа 2018

У меня есть элемент формы, созданный из Angular Material, который представляет собой поле для выбора страны с автозаполнением:

<mat-form-field>
  <input type="text" placeholder="Country" aria-label="Number" matInput formControlName="country" [matAutocomplete]="auto">
  <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
    <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
      {{ option.name }}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

В ngOnInit я вызываю API, и это заполняет фильтрованные параметры.

Поскольку я собираюсь использовать этот сборщик во многих формах, я хочу сделать его компонентом. Как только я переместил код в компонент, я получил:

SelectCountryComponent.html: 2 Ошибка ОШИБКИ: должно быть указано formControlName используется с родительской директивой formGroup. Вы хотите добавить formGroup директиву и передайте ей существующий экземпляр FormGroup (вы можете создать его в своем классе).

Даже если я использую свой компонент в FormGroup, он все равно выдает эту ошибку. Каков будет правильный подход для создания компонента, который содержит formControl?

выберите-country.component.ts

@Component({
  selector: 'app-select-country',
  templateUrl: './select-country.component.html',
  styleUrls: ['./select-country.component.css']
})
export class SelectCountryComponent implements OnInit {

  countryFormGroup = new FormGroup({
    country: new FormControl('')
  });

  options: Country[];
  filteredOptions: Observable<Country[]>;

  constructor(public api: ApiService) {

  }

  ngOnInit() {

    this.api.get('country').subscribe(res => {
      console.log(res);
      this.options = res;
      this.filteredOptions = this.countryFormGroup.get('country').valueChanges.pipe(
        startWith<string | Country>(''),
        map(value => (typeof value === 'string' ? value : value['name'])),
        map(name => name ? this._filter(name) : this.options ? this.options.slice() : [])
      );
    });

  }

  displayFn(country?: Country): string | undefined {
    return country ? country.name : undefined;
  }

  private _filter(name: string): Country[] {
    const filterValue = name.toLowerCase();

    return this.options.filter(
      option => option.name.toLowerCase().indexOf(filterValue) === 0
    );
  }

}

выберите-country.component.html

<mat-form-field>
  <input type="text" placeholder="Country" aria-label="Number" matInput formControlName="country" [matAutocomplete]="auto">
  <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
    <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
      {{ option.name }}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

В вашем случае:

<form [formGroup]="countryFormGroup" (ngSubmit)="onSubmit()">
  <mat-form-field>
    <input type="text" placeholder="Country" aria-label="Number" matInput formControlName="country" [matAutocomplete]="auto">
  </mat-form-field>
</form>

Вам необходимо связать countryFormGroup с формой [formGroup]="countryFormGroup" и использовать внутри нее formControlName.

Чтобы сделать ваш код чище, вы можете фильтровать опции, используя pipe в HTML

0 голосов
/ 28 августа 2018

Оберните ваше поле mat-form в div или form с [formGroup] = "countryFormGroup". Вам нужно привязать созданную форму formGroup к шаблону.

<div [formGroup]="countryFormGroup">
<mat-form-field>
  <input type="text" placeholder="Country" aria-label="Number" matInput formControlName="country" [matAutocomplete]="auto">
  <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
    <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
      {{ option.name }}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>
</div>
...