Отправка реактивной формы Angular и четкая проверка

У меня реактивная форма

 <form [formGroup]="secondFormGroup">
      <ng-template matStepLabel>enter items</ng-template>
      <div style="display: flex; flex-direction: column;">
        <mat-form-field>
          <input matInput type="text" placeholder="category"  [(ngModel)]="newItem.CategoryName" formControlName="category"
          />
        </mat-form-field>
        <mat-form-field>
          <input matInput type="text" placeholder="sub category"  [(ngModel)]="newItem.SubCategoryName" formControlName="subCategory"
          />
        </mat-form-field>
        <mat-form-field>
          <input matInput type="text" placeholder="product"  [(ngModel)]="newItem.ProductName" formControlName="name"/>
        </mat-form-field>
        <mat-form-field>
          <input matInput  [(ngModel)]="newItem.Amount" type="number" min="0" placeholder="amount" formControlName="amount"
          />
        </mat-form-field>
        <mat-form-field>
          <input matInput  [(ngModel)]="newItem.Price" type="number" min="0" placeholder="price" formControlName="price"
          />
        </mat-form-field>
        <button mat-raised-button color="primary" (click)="AddNewProduct(newItem)" style="float: left; align-self: flex-end;">submit</button>
      </div>
    </form>

Я инициализирую его так:

 this.secondFormGroup = this._formBuilder.group({
  category: ['', Validators.required],
  subCategory: ['', Validators.required],
  name: ['', Validators.required],
  amount: ['', Validators.required],
  price: ['', Validators.required]
});

При нажатии sumbit я вызываю этот метод:

AddNewProduct(newProduct) {
if (this.secondFormGroup.valid) {
  //add product
  this.secondFormGroup.reset();
 } 
}

После добавления продукта очищаю форму. Однако после очистки формы возникают ошибки проверки. Я хочу, чтобы ошибки проверки отображались только тогда, когда пользователь нажимает кнопку «Отправить», а форма недействительна, а не когда я очищаю форму после отправки.

Как я могу это исправить?


person amitairos    schedule 01.07.2018    source источник


Ответы (4)


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

Вместо этого вам нужно будет вызвать resetForm, который находится в FormGroupDirective:

@ViewChild(FormGroupDirective) formGroupDirective: FormGroupDirective;

this.formGroupDirective.resetForm();

Во-вторых, вам нужно заключить его в setTimeout с таймаутом 0, чтобы форма была отправлена ​​до ее сброса.

setTimeout(() => this.formGroupDirective.resetForm(), 0)

Я тестировал это в StackBlitz, и, похоже, все работает:

https://stackblitz.com/edit/angular-l6xq1d?file=src%2Fapp%2Fapp.component.ts

person user184994    schedule 01.07.2018
comment
Спасибо. Хотя в моем коде форма не очищается после вызова resetForm. Почему это? - person amitairos; 01.07.2018
comment
Трудно сказать, не увидев этого. У вас есть ошибки в консоли? - person user184994; 01.07.2018
comment
Нашел ошибку. У меня другая форма. Когда снимаю, работает - person amitairos; 01.07.2018
comment
Как мне получить доступ только к formGroupDirective второй формы? - person amitairos; 01.07.2018
comment
Дайте ему идентификатор, например #myForm="ngForm", а затем используйте вместо этого @ViewChild('myForm') formGroupDirective: FormGroupDirective; - person user184994; 01.07.2018
comment
Спасибо! Добавлю, что не следует (!) Сбрасывать группу форм. Это и не более того. - person JFFIGK; 13.03.2020
comment
работает в угловом 10/9/8 - person SHUBHASIS MAHATA; 02.02.2021

Это работает, попробуйте это, вам нужно сбросить formDirective, иначе он не будет на 100% отдыхать в форме

Шаблон:

<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();
  }
}
person Akitha_MJ    schedule 08.01.2019

Вы можете легко очистить validators формы с помощью clearValidators()

this.secondFormGroup .clearValidators();
this.secondFormGroup .updateValueAndValidity();

Но это удалит валидаторы из фактической группы форм, и они не будут отображать errors при отправке формы в следующий раз.

Лучше сделать это:

Вы можете просто использовать флаг в шаблоне ошибки, чтобы отображать ошибки на основе отправки / сброса формы. И установите / сбросьте флаг соответственно.

public formSubmitted = false;

onSubmit(){
   this.formSubmitted = true;
}

reset(){
   this.formSubmitted = false;
}

файл шаблона

<div *ngIf="formSubmitted">
 display errors
</div>
person Amit Chigadani    schedule 01.07.2018
comment
Спасибо, но я не хочу просто показывать или скрывать элемент ошибки. Я хочу выделить поля красным, как это делается в стиле по умолчанию. - person amitairos; 01.07.2018
comment
Я добавил больше описания того, что произойдет, если вы очистите валидаторы. Пожалуйста, проверьте это. - person Amit Chigadani; 01.07.2018

Если вы используете входы Angular Material, вы можете скрыть состояние ошибки, установив входы как untouched. В полях ввода материала отображается состояние ошибки только при касании ввода.

So

this.secondFormGroup.markAsUntouched();

должен сделать свое дело.

Возможно, вам придется запустить запуск обнаружения изменений после такой операции (в зависимости от сценария)

Вот вам доказательство концепции. Вход изначально находится в состоянии ошибки. Специальная кнопка очищает это состояние до будущего ввода.

https://stackblitz.com/edit/angular-tadkmb?file=src%2Fapp%2Fapp.component.ts

person Antoniossss    schedule 01.07.2018
comment
На самом деле, вызов сброса в любом случае отмечает их как нетронутые - person user184994; 01.07.2018
comment
@ user184994 Полезно знать, спасибо за отзыв. Но подождите, OP заявляет, что сбрасывает форму .. - person Antoniossss; 01.07.2018
comment
@amitairos ofc, это работает, просто вы не знаете, как его использовать. Заявление о том, что он не работает, для меня ничего не значит, так как в вашем случае может быть 10000 причин, по которым он не работает. Я могу только догадываться, что вам нужно запустить обнаружение изменений, как я сказал в последнем предложении. - person Antoniossss; 01.07.2018
comment
@Antoniossss Пробовал использовать обнаружение изменений, но ошибки все равно отображаются. - person amitairos; 01.07.2018
comment
Пожалуйста, создайте для нас stackblitz, это будет намного проще - person Antoniossss; 01.07.2018
comment
Я могу помочь с этим: stackblitz.com/edit/. Проблема, похоже, в том, что форма помечается как отправленная после вызова сброса, и это значение никогда не сбрасывается. Если форма помечена как отправленная, независимо от того, является ли она нетронутой, ошибки будут выделены. - person user184994; 01.07.2018
comment
@amitairos благодаря user184994 Я добавил stackblitz с POC. Работает так, как я описал. - person Antoniossss; 01.07.2018
comment
пользовательские - реактивные формы не имеют состояния отправки. Это всего лишь интерфейс между UI и моделью данных :) - person Antoniossss; 01.07.2018
comment
@Antoniossss На самом деле это было свойство на https://angular.io/api/forms/FormGroupDirective, и оно используется средством проверки ошибок материала, как описано в https://github.com/angular/material2/issues/7522. Как я уже упоминал в своем ответе выше, вызов resetForm в setTimeout должен справиться с этим. - person user184994; 01.07.2018