Почему поле mat-form-field нельзя редактировать внутри этого массива FormArray? - PullRequest
1 голос
/ 10 мая 2019

Следующая форма делает почти то, что должна, за исключением того, что я не могу редактировать внутри нее mat-form-field s. Они не отключены, их просто невозможно отредактировать.

В чем причина?

См .: StackBlitz

Я не вижу разницы с в этом примере в StackBlitz.

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

@Component({
  selector: 'form-field-label-example',
  templateUrl: 'form-field-label-example.html',
  styleUrls: ['form-field-label-example.css'],
})
export class FormFieldLabelExample {

  public dataList = [
    {name: 'Alice'},
    {name: 'Bob'}
  ]

  public form: FormGroup;

  constructor(private _fb: FormBuilder) {

    const formArray = this._fb.array([]);  

    for (const data of this.dataList) {
      formArray.push(
        this._fb.group({name: new FormControl(data.name)})
      );      
    }

    this.form = this._fb.group({
      offers: formArray
    });

  }

}
<div>

  <form [formGroup]="form">

    <div formArrayName="offers" *ngFor="let data of form.controls.offers?.value; let i = index;">
      <ng-container [formGroupName]="i">
        <mat-form-field>
          <input matInput placeholder="Name" formControlName="name">
        </mat-form-field>
      </ng-container>
    </div>

  </form>

  <span *ngIf="form.dirty">DIRTY</span>

  <mat-form-field>
    <input matInput placeholder="Name">
  </mat-form-field>

</div>

Ответы [ 2 ]

4 голосов
/ 10 мая 2019

Это действительно связано с поведением рендеринга ngFor.

Точнее, если массив, используемый в ngFor, изменяет ссылки на элементы этого массива (и мы не предоставили настраиваемую функцию trackBy для переопределениясравнение), тогда Angular распознает эти изменения и повторно отобразит представление.enter image description here

Угловые формы часто могут запускать метод AbstractControl.updateValueAndValidity для всей иерархии элементов управления.

FormControl -> parent -> FormGroup -> parent -> FormArray -> parent -> FormGroup

Для FormGroup он вызываетследующий метод:

_updateValue(): void { (this as{value: any}).value = this._reduceValue(); }

, который в основном создает новый объект, т. е. {name: 'Alice'} При следующем запуске он заменит текущее значение новым.

{name: 'Alice'} !== {name: 'Alice'}

Это точноэта угловая разница по умолчанию распознается в директиве ngForOf.

Вы можете спросить?

Тогда почему я не вижу разницы с в этом примере в StackBlitz?

В этом примере проблема все еще существует, но ее не видно с первого взгляда.

|username  password
  /\
click here(it works)

username  password
            /\
     then click here(it doesn't since the dom was rerendered)

Разница между вашим примером и приведенным выше примером заключается в том, что вы используете элементы управления материалом и триггер AbstractControl.updateValueAndValidity происходит раньше.

Так в чем же решение?

1) Упомянутое ранее свойство trackBy

trackByFn(index) {
  return index;
}

*ngFor="let data of form.controls.offers?.value; let i = index; trackBy: trackByFn"

Пример Stackblitz

2) Присвойте this.form.controls.offers.value свойству компонента и используйте его.

arr;
...
this.arr = this.form.controls.offers.value;

*ngFor="let data of arr; let i = index;"

Пример Stackblitz

0 голосов
/ 10 мая 2019

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

https://stackblitz.com/edit/angular-ckpey4-bxiidz?file=app/form-field-label-example.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...