Компонент некорректно работает с FormArray и formGroupName

Вопрос или проблема

Поле ввода не отображается с внешним видом mat-form-field до щелчка внутри, когда используется formGroupName с FormArray.

Смотрите пример:

TS:

formMain = this.fb.group({
    details: this.fb.array([
      new FormGroup({
        label: new FormControl(''),
        description: new FormControl(''),
      }),
    ]),
  });

  get detailsFormArray() {
    return this.formMain.controls.details as FormArray;
  }

  addDetails() {
    this.detailsFormArray.push(this.fb.control(''));
  }
}

HTML:

<form [formGroup]="formMain">
  <div formArrayName="details">
    <div
      *ngFor="let detail of detailsFormArray.controls; index as i"
      [formGroupName]="i"
    >
      <mat-form-field appearance="fill">
        <mat-label>Этикетка детали</mat-label>
        <input id="detail-label" matInput type="text" formControlName="label" />
      </mat-form-field>

      <mat-form-field appearance="fill">
        <mat-label>Описание детали</mat-label>
        <input
          id="detail-description"
          matInput
          type="text"
          formControlName="description"
        />
      </mat-form-field>
    </div>
  </div>
</form>

<br />

<button type="button" (click)="addDetails()">+ Добавить детали</button>


После нажатия на Добавить детали и до нажатия на форму:

и

и после нажатия на форму:

Есть ли решение этой проблемы?

Вы неправильно добавляете экземпляр FormGroup в details FormArray. В настоящее время вы добавляете экземпляр FormControl.

Рекомендуем написать общую функцию для создания экземпляра FormGroup.

formMain = this.fb.group({
  details: this.fb.array([this.addDetailsFormGroup()]),
});

addDetails() {
  this.detailsFormArray.push(this.addDetailsFormGroup());
}

addDetailsFormGroup() {
  return new FormGroup({
    label: new FormControl(''),
    description: new FormControl(''),
  });
}

Демонстрация @ StackBlitz

Ответ или решение

Проблема, с которой вы столкнулись, связана с неправильным добавлением экземпляра FormGroup в массив FormArray. В текущей реализации вы добавляете экземпляр FormControl, что приводит к неправильному отображению полей ввода внутри компонента <mat-form-field>.

Для корректного отображения элементов формы, вам необходимо создать и добавить экземпляр FormGroup, который будет содержать необходимые контролы (label и description). Я рекомендую создать вспомогательную функцию, которая будет возвращать новый экземпляр FormGroup с нужными контроллерами. Ниже приведен исправленный код:

TypeScript (TS)

import { Component } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, FormArray } from '@angular/forms';

@Component({
  selector: 'app-your-component',
  templateUrl: './your-component.component.html',
  styleUrls: ['./your-component.component.css']
})
export class YourComponent {
  formMain = this.fb.group({
    details: this.fb.array([this.createDetailsFormGroup()]),
  });

  constructor(private fb: FormBuilder) {}

  get detailsFormArray(): FormArray {
    return this.formMain.get('details') as FormArray;
  }

  addDetails() {
    this.detailsFormArray.push(this.createDetailsFormGroup());
  }

  private createDetailsFormGroup(): FormGroup {
    return this.fb.group({
      label: new FormControl(''),
      description: new FormControl(''),
    });
  }
}

HTML

<form [formGroup]="formMain">
  <div formArrayName="details">
    <div *ngFor="let detail of detailsFormArray.controls; index as i" [formGroupName]="i">
      <mat-form-field appearance="fill">
        <mat-label>Label of a detail</mat-label>
        <input id="detail-label" matInput type="text" formControlName="label" />
      </mat-form-field>

      <mat-form-field appearance="fill">
        <mat-label>Description of a detail</mat-label>
        <input id="detail-description" matInput type="text" formControlName="description" />
      </mat-form-field>
    </div>
  </div>
</form>

<br />

<button type="button" (click)="addDetails()">+ Add Details</button>

Объяснение

  1. Создание экземпляра FormGroup: Мы создали метод createDetailsFormGroup(), который возвращает новый FormGroup с контролами label и description. Это позволяет вам легко управлять структурой формы.

  2. Исправление метода addDetails(): Теперь данный метод вызывает createDetailsFormGroup(), что гарантирует, что в массив FormArray добавляется правильный экземпляр FormGroup.

Заключение

С этими изменениями ваше поле ввода будет корректно отображаться с нужным стилем и поведением при добавлении новых деталей. Если вы хотите протестировать это решение, вы можете использовать предоставленную ссылку на StackBlitz, чтобы быстро понять, как все работает.

Если у вас есть дополнительные вопросы или необходима помощь, не стесняйтесь обращаться!

Оцените материал
Добавить комментарий

Капча загружается...