Сброс угловых реактивных значений FormArray - PullRequest
0 голосов
/ 24 августа 2018

Я столкнулся со странной ошибкой с угловыми реактивными формами.Я использую FormArray, чтобы создать форму, где поля могут быть добавлены или удалены.Я также хочу иметь возможность сбросить форму, в результате чего значения и количество входных данных формы возвращаются к исходной сумме.В настоящее время я могу создать экземпляр формы, добавить поля и удалить их, но когда я нажимаю reset, я создал созданную функцию, которая очищает FormArray, а затем воссоздает поля, используя тот же процесс, который я использовал для первоначальной настройки формы., значение не отображается должным образом.Я не уверен, почему это происходит, возможно, это связано с formControlNames, используемым для связывания формы в html?

Кто-нибудь знает, что является причиной проблемы или как правильно сбросить значения формы?

Я создал стек стека здесь: https://stackblitz.com/edit/angular-reactive-formarray-bug

Вот мой код компонента.

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

import { ContentTemplate, ContentTemplateEntry, NewContentEntry } from './models';

import {Observable, Subscription, of} from 'rxjs';

import data from './template-data.json';

@Component({
  selector: 'material-app',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent {
  public templateForm: FormGroup;

  public contentTemplate$: Observable<ContentTemplate>;
  public activeTemplate: ContentTemplate;
  public templateSub: Subscription;
  public entries: ContentTemplateEntry[];

  get templateEntries(): FormArray {
    return <FormArray>this.templateForm.get('entries');
  }

  constructor(
    private fb: FormBuilder
  ) {
    this.contentTemplate$ = of(data)
  }

  ngOnInit(): void {
    this.templateSub = this.contentTemplate$.subscribe((template: ContentTemplate) => {
      this.activeTemplate = {...template};
      this.entries = [...template.entries];
      this.templateForm = this.fb.group({
        entries: this.fb.array([])
      });
      this._processEntries(this.entries);
    });
  }

  ngOnDestroy(): void {
    this.templateSub.unsubscribe();
  }

  private _buildEntry(entry: ContentTemplateEntry) {
    const g = this.fb.group({
      id: {value: entry.id},
      title: {value: entry.title, disabled: entry.isRequired},
      orderNumber: {value: entry.orderNumber},
      type: {value: entry.type}
    });
    return g;
  }

  private _processEntries(entries: ContentTemplateEntry[])  {
    entries.forEach((e, i) => {
      this.templateEntries.push(this._buildEntry(e));
    });
  }

  private _getOrderNumber(): number {
    return this.templateEntries.length + 1;
  }

  private _removeItemsFromEntries(): void {
    while (this.templateEntries.length > 0) {
      this.templateEntries.removeAt(0);
    }
  }

  // reinstantiate using the same approach as before
  public resetForm() {
    this._removeItemsFromEntries();
    this._processEntries(this.entries);
  }

  public removeEntry(id: number) {
    this.templateEntries.removeAt(id);
  }

  public addEntry() {
    this.templateEntries.push(
      this._buildEntry(new NewContentEntry({
        orderNumber: this._getOrderNumber()
      }))
    );
  }

  public save() {
    console.log('save triggered');
  }
}

Ответы [ 4 ]

0 голосов
/ 27 апреля 2019

Лучше так:

const control = <FormArray>this.templateForm.controls['entries'];
while (control.length > 0) {
  control.removeAt(0)
}
0 голосов
/ 29 августа 2018

Я думаю, что это проблема с асинхронными операциями в реактивных формах. setTimeout исправляет эту проблему, но я думаю, что это не лучший способ.

public resetForm() {
  setTimeout(() => this._processEntries(this.entries));
}

Также вы можете изменить свой метод processEntries.

private _processEntries(entries: ContentTemplateEntry[]) {
  const resEntries = entries.map(e => this._buildEntry(e));
  this.templateForm.setControl('entries', this.fb.array(resEntries));
}

И _removeItemsFromEntries больше не нужно.

пример здесь https://stackblitz.com/edit/angular-reactive-formarray-bug-pvj4cm

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

Ваша ошибка вызвана type="reset" на кнопке сброса.Удаление этого атрибута или замена на type="button" решит проблему.

Правильный способ сброса формы - вызов метода reset() для вашего свойства templateForm.

Сбрасывает FormGroup, помечает всех потомков помеченными как нетронутые и нетронутыми, а значение всех потомков равно нулю.

Официальная документация FormGroup

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

Я использовал один раз FormArray, и я сделал следующее:

const control = <FormArray>this.templateForm.controls['entries'];
for(let i = control.length-1; i >= 0; i--) {
  control.removeAt(i)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...