Angular 5 FormGroup reset не выполняет валидаторы reset

У меня есть форма на моей странице, и когда я вызываю FormGroup.reset() он устанавливает класс форм в ng-pristine ng-untouched но FormControl.hasError(...) прежнему возвращает truey. Что я здесь не так делаю?

шаблон

<form [formGroup]="myForm" (ngSubmit)="submitForm(myForm)">
  <mat-form-field>
    <input matInput formControlName="email" />
    <mat-error *ngIf="email.hasError('required')">
      Email is a required feild
    </mat-error>
  </mat-form-field>
  <mat-form-field>
    <input matInput type="password" formControlName="password" />
    <mat-error *ngIf="password.hasError('required')">
      Password is a required feild
    </mat-error>
  </mat-form-field>
  <button type="submit">Login</button>
</form>

Составная часть

export class MyComponent {
  private myForm: FormGroup;
  private email: FormControl = new FormContorl('', Validators.required);
  private password: FormControl = new FormControl('', Validators.required);

  constructor(
    private formBuilder: FormBuilder
  ) {
    this.myForm = formBuilder.group({
      email: this.email,
      password: this.password
    });
  }

  private submitForm(formData: any): void {
    this.myForm.reset();
  }
}

Plunker

http://embed.plnkr.co/Hlivn4/

Ответ 1

Он (FormGroup) ведет себя правильно. Ваша форма требует имени пользователя и пароля, поэтому, когда вы reset форма должна быть недействительной (т.е. Форма без имени пользователя/пароля недействительна).

Если я правильно понял, ваша проблема заключается в том, почему красные ошибки отсутствуют в первый раз, когда вы загружаете страницу (где форма ТАКЖЕ неверна), но всплывают при нажатии кнопки. Эта проблема особенно заметна, когда вы используете материал.

AFAIK, <mat-error> проверить достоверность FormGroupDirective, а не FormGroup, а сброс FormGroup не reset FormGroupDirective. Это немного неудобно, но для очистки <mat-error> вам понадобится reset FormGroupDirective.

Для этого в шаблоне определите переменную как таковую:

<form [formGroup]="myForm" #formDirective="ngForm" 
  (ngSubmit)="submitForm(myForm, formDirective)">

И в вашем классе компонента вызовите formDirective.resetForm():

private submitForm(formData: any, formDirective: FormGroupDirective): void {
    formDirective.resetForm();
    this.myForm.reset();
}

Проблема GitHub: https://github.com/angular/material2/issues/4190

Ответ 2

После прочтения комментариев это правильный подход

// you can put this method in a module and reuse it as needed
resetForm(form: FormGroup) {

    form.reset();

    Object.keys(form.controls).forEach(key => {
      form.get(key).setErrors(null) ;
    });
}

Не было необходимости вызывать form.clearValidators()

Ответ 3

В дополнение к решению Harry Ninh, если вы хотите получить доступ к formDirective в своем компоненте без необходимости выбора кнопки формы, то:

Шаблон:

<form 
  ...
  #formDirective="ngForm" 
>

Составная часть:

import { ViewChild, ... } from '@angular/core';
import { NgForm, ... } from '@angular/forms';

export class MyComponent {
 ...
 @ViewChild('formDirective') private formDirective: NgForm;

  constructor(... )

  private someFunction(): void { 
    ...
    formDirective.resetForm();
  }
}

Ответ 4

У меня тоже был такой же набор проблем. Моя проблема заключалась в том, что я использовал mat-form-field и formGroup. После сброса формы submitted флаг не сбрасывался.

Итак, решение, которое сработало для меня, заключается в том, чтобы поместить директиву ngForm вместе с formGroup и передать onSubmit(form). Добавлена @ViewChild('form') form; в компоненте, а затем я использовал this.form.resetForm();

Ответ 5

Я обнаружил, что после вызова resetForm() и reset() отправленные данные не сбрасывались и оставались верными, что приводило к отображению сообщений об ошибках. Это решение сработало для меня. Я нашел это, когда искал решение для вызова select() и focus() для входного тега, который также не работал должным образом. Просто оберните ваши строки в setTimeout(). Это немного взломать, но делает свое дело.

<form [formGroup]="myFormGroup" #myForm="ngForm">
    …
    <button mat-raised-button (click)="submitForm()">
</form>
submitForm() { 
    …
    setTimeout(() => {
        this.myForm.resetForm();
        this.myFormGroup.reset();
    }, 0);
}

Ответ 6

Приведенное ниже решение работает для меня при попытке сброса определенного контроллера формы в группе форм -

 this.myForm.get('formCtrlName').reset();
 this.myForm.get('formCtrlName').setValidators([Validators.required, Validators.maxLength(45), Validators.minLength(4), Validators.pattern(environment.USER_NAME_REGEX)]);
 this.myForm.get('formCtrlName').updateValueAndValidity();

Ответ 7

Переместите функцию отправки с вашей формы на вашу кнопку и добавьте типы для ваших кнопок:

<form [formGroup]="createForm">
  <button (click)="submitForm()" type="submit">Submit</button>
  <button (click)="createForm.reset()" type="reset">Reset</button>
</form>