11

I have an angular template driven form. and I want to reset all the validation error and make it as untouched without resetting the form. How to do that in angular? I have tried the following method

onAdd(form: NgForm) {

form.form.markAsPristine();
form.form.markAsUntouched();

}

but this doesn't work.

link:- https://stackblitz.com/edit/angular-ezixd4

current behavior:- when I click to submit an empty form, all the field is marked with error and when I click add it adds the field but the above function doesn't remove the error message.

expected behavior:- when I click to submit an empty form, all the field is marked with error and when I click add it adds the field and it should remove the error message on the form (or in the added files).

In this form, I am adding input field with add Button and I want to clear any error message before the user has the chance to interact with the form.

rahul Kushwaha
  • 2,395
  • 7
  • 32
  • 64
  • Try this with `@ViewChild()` and you will find more information on given [link](https://stackoverflow.com/questions/34608361/how-to-reset-form-validation-on-submission-of-the-form-in-angular-2) – Denuka Apr 20 '19 at 20:01
  • So if your form is invalid (because of invalid values in controls) and you make it pristine but not remove the invalid values, won't your form still be invalid. – Ashish Ranjan Apr 20 '19 at 20:05
  • I have tried `@ViewChild()` but still it doesn't work. – rahul Kushwaha Apr 20 '19 at 20:09
  • @xyz yes but that's why I want to make it untouched, and if user click submits again with the invalid value the error will show up again. – rahul Kushwaha Apr 20 '19 at 20:11
  • The real reason I want to have this behavior because I am adding input field dynamically by `add button` since the newly added input field will be empty then it is showing error before the user has a chance to interact with it. – rahul Kushwaha Apr 20 '19 at 20:14
  • @rahulKushwaha so, this should work. Please show how you add a new input field. – Ashish Ranjan Apr 20 '19 at 20:31
  • Your code works perfectly, just tried it. Please create a stackblitz showcasing the issue. – AT82 Apr 21 '19 at 19:27
  • @AJT_82 there you go, I have added stackblitz. – rahul Kushwaha Apr 24 '19 at 17:31
  • Yaah, the code is a bit different than what you showed, or shall we say it wasn't complete before. Now I see the issue. I'll see if I can figure something out, let you know if I do :) I think I've seen this before, but I'll still check if I'm correct. – AT82 Apr 24 '19 at 18:13

8 Answers8

11

This finally worked for me:

this.form.reset();
Object.keys(this.form.controls).forEach(key => {
    this.form.get(key).setErrors(null) ;
});
gal007
  • 6,911
  • 8
  • 47
  • 70
5

With Angular Material, you need to define FormGroupDirective As well with FormGroup and FormControl

@ViewChild(FormGroupDirective) formGroupDirective: FormGroupDirective;

import { FormGroup, FormControl, FormGroupDirective } from '@angular/forms';

Reset FormGroupDirective in the onSubmit method with reactive form reset.

this.formGroupDirective.resetForm();
<br>
this.form.reset();

If the above FormGroupDirective reset does not work, try it with a timeout of 0 second

setTimeout(() => this.formGroupDirective.resetForm(), 0);
mr fat
  • 75
  • 1
  • 9
Neha Prajapati
  • 111
  • 2
  • 3
4

the class mat-input-invalid depends partly on the submitted state of the form. So when you submit the form, the submitted property is switched to true. markAsPristine() or markAsUntouched() does not reset the submitted flag, thus the errors still show. I see two possibilities. One quick and dirty, which when I tested seems to work in your case. I cannot promise that it will in all cases, but you can experiment around with it and see if it will work. That is, you call resetForm() which does reset the submitted property. But yes, you want to keep the values that are set.. so, we pass the value of the current state of the form in the reset:

onAdd(form: NgForm) {
  this.specification.push(++this.num);
  form.resetForm(form.value);  
}

DEMO

So that was the dirty way, a more controlled way would be to use the ErrorStateMatcher, that is also mentioned in the docs. With that you can choose when to show the error messages.

AT82
  • 71,416
  • 24
  • 140
  • 167
  • yeah, that make sense, i actually want to remove error from the newly added field before user have a chance to interact with it. – rahul Kushwaha Apr 24 '19 at 20:44
3

Make sure there is no button inside form section. Addnew button should be outside of form.

3
 resetForm() {
    this.myFormGroup.reset();
    this.myFormGroup.setErrors(null); // could be removed
    this.myFormGroup.updateValueAndValidity();
  } 
S. V
  • 1,085
  • 5
  • 5
2

You could just iterate over each required field and call their setErrors method while passing null onto them:

YOUR_FORM.controls.YOUR_FIELD_NAME.setErrors(null);

for instance when you have a username and password field:

this.loginForm.controls.username.setErrors(null);
this.loginForm.controls.password.setErrors(null);

Hope this helps!

Blauharley
  • 4,186
  • 6
  • 28
  • 47
  • I believe he is only displaying errors and preventing the form submit if the form is touched. If he is marking the form as pristine and untouched, his logic should actually work. – Ashish Ranjan Apr 20 '19 at 20:47
  • thanks for your reply, but it completely removes the error, I want to error reappear if the user still doesn't interact with the form, however from the above approach it removes the error completely and it allows the form to submit. – rahul Kushwaha Apr 21 '19 at 06:50
  • Can your form really be submitted after removing all errors? With my form an error reappears when I submit my form again because within my submit-listener it is checked whether the form-property invalid is true or false. The form-validation and field-values are actually not removed but only the error-messages. – Blauharley Apr 21 '19 at 08:00
0

You can do it with a more generic way:

reset(formGroup: FormGroup) {
   Object.keys(formGroup.controls).forEach(
      field => {
         formGroup.get(field).setErrors(null);
      }
    );
}
...
this.reset(yourForm);
...
Juan Antonio
  • 2,451
  • 3
  • 24
  • 34
0

I had to do this, put a timeout in so that the blur event prior to clicking a button didn't get handled after the cancel button click:

let timeout = setTimeout(function() {
  Object.keys(originalValues).forEach(controlName => {
    let control =that.getControl(controlName);
    control.setValue(originalValues[controlName]);
    control.markAsUntouched();
    control.setErrors(null);
    control.markAsPristine();
  });
  this.setControlState(formName);
  clearTimeout(timeout);
}, 10);
GeeWhizBang
  • 699
  • 4
  • 27