64

I am aware that Angular 2 currently lacks a way to easily reset a form to a pristine state. Poking around I have found a solution like the one below that resets the form fields.

It has been suggested that I need to drop the control group and create a new one to rebuild the form as pristine. I am having difficulty figuring out the best way to do this. I know I need to wrap the form building within a function but I am running into errors when doing that within the constructor.

What would be the best way to rebuild the control group to completely reset the form?

class App {

    name: Control;
    username: Control;
    email: Control;

    form: ControlGroup;

    constructor(private builder: FormBuilder) {

        this.name = new Control('', Validators.required);
        this.email = new Control('', Validators.required);
        this.username = new Control('', Validators.required);

        this.form = builder.group({
            name: this.name,
            email: this.email,
            username: this.username
        });
    }

    onSubmit(value: any): void {  
        // code that happens when form is submitted
        // then reset the form
        this.reset();
    }

    reset() {
        for (let name in this.form.controls) {
            this.form.controls[name].updateValue('');
            this.form.controls[name].setErrors(null);
        }
    }
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
lukemcd
  • 1,471
  • 2
  • 15
  • 24
  • The question is a bit different but I think the answer is the same. – Günter Zöchbauer Apr 15 '16 at 20:05
  • Günther, the question you refer to does not show how to remove and recreate a control group. This is what I am asking. I think it would be helpful if someone could show the best way to do this. – lukemcd Apr 15 '16 at 21:29
  • you can use `ngModel` instead of `ngControl` for form in angular2 may be because ngControl did't support yet properly for reset control after submitting form. – Pardeep Jain Apr 16 '16 at 20:20

12 Answers12

90

>= RC.6

Support resetting forms and maintain a submitted state.

console.log(this.form.submitted);
this.form.reset()

or

this.form = new FormGroup()...;

importat update

To set the Form controls to a state when the form is created, like validators, some additional measurements are necessary

In the view part of the form (html) add an *ngIf to show or hide the form

<form *ngIf="showForm"

In the component side of the form (*.ts) do this

  showForm:boolean = true;

  onSubmit(value:any):void {
    this.showForm = false;
    setTimeout(() => {
    this.reset()
      this.showForm = true;
    });
  }

Here is a more detailed example:

export class CreateParkingComponent implements OnInit {
  createParkingForm: FormGroup ;
  showForm = true ;

  constructor(
    private formBuilder: FormBuilder,
    private parkingService: ParkingService,
    private snackBar: MatSnackBar) {

      this.prepareForm() ;
  }

  prepareForm() {
    this.createParkingForm = this.formBuilder.group({
      'name': ['', Validators.compose([Validators.required, Validators.minLength(5)])],
      'company': ['', Validators.minLength(5)],
      'city': ['', Validators.required],
      'address': ['', Validators.compose([Validators.required, Validators.minLength(10)])],
      'latitude': [''],
      'longitude': [''],
      'phone': ['', Validators.compose([Validators.required, Validators.minLength(7)])],
      'pictureUrl': [''],
      // process the 3 input values of the maxCapacity'
      'pricingText': ['', Validators.compose([Validators.required, Validators.minLength(10)])],
      'ceilingType': ['', Validators.required],
    });
  }

  ngOnInit() {
  }


  resetForm(form: FormGroup) {
    this.prepareForm();
  }

  createParkingSubmit() {
    // Hide the form while the submit is done
    this.showForm = false ;

    // In this case call the backend and react to the success or fail answer

    this.parkingService.create(p).subscribe(
      response => {
        console.log(response);
        this.snackBar.open('Parqueadero creado', 'X', {duration: 3000});
        setTimeout(() => {
          //reset the form and show it again
          this.prepareForm();
            this.showForm = true;
          });
      }
      , error => {
        console.log(error);
        this.showForm = true ;
        this.snackBar.open('ERROR: al crear Parqueadero:' + error.message);
      }
      );
  }
}

Plunker example

original <= RC.5 Just move the code that creates the form to a method and call it again after you handled submit:

@Component({
  selector: 'form-component',
  template: `
    <form (ngSubmit)="onSubmit($event)" [ngFormModel]="form">
       <input type="test" ngControl="name">
       <input type="test" ngControl="email">
       <input type="test" ngControl="username">
       <button type="submit">submit</button>
    </form>
    <div>name: {{name.value}}</div>
    <div>email: {{email.value}}</div>
    <div>username: {{username.value}}</div>
`
})
class FormComponent {

  name:Control;
  username:Control;
  email:Control;

  form:ControlGroup;

  constructor(private builder:FormBuilder) {
    this.createForm();
  }

  createForm() {
    this.name = new Control('', Validators.required);
    this.email = new Control('', Validators.required);
    this.username = new Control('', Validators.required);

    this.form = this.builder.group({
      name: this.name,
      email: this.email,
      username: this.username
    });
  }

  onSubmit(value:any):void {
    // code that happens when form is submitted
    // then reset the form
    this.reset();
  }

  reset() {
    this.createForm();
  }
}

Plunker example

Mauricio Gracia Gutierrez
  • 10,288
  • 6
  • 68
  • 99
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
29

Use NgForm's .resetForm() rather than .reset() because it is the method that is officially documented in NgForm's public api. (Ref [1])

<form (ngSubmit)="mySubmitHandler(); myNgForm.resetForm()" #myNgForm="ngForm">

The .resetForm() method will reset the NgForm's FormGroup and set it's submit flag to false (See [2]).

Tested in @angular versions 2.4.8 and 4.0.0-rc3

Somo S.
  • 3,997
  • 4
  • 26
  • 33
  • I don't know, I see `reset()` documented [here](https://angular.io/docs/ts/latest/guide/forms.html). – Jason Swett Apr 27 '17 at 10:30
  • 1
    @jason that's a "guide" ( basically a tutorial).. What I posted however, is the API reference... So depends on what you consider as a better source of truth. I think if you are doing serious work you look through the latter wherever possible.. Obviously Angular Team could really do some work to make all their documentation consistent – Somo S. Apr 27 '17 at 20:28
  • 1
    there is only `reset()` – Mustafa Sep 24 '17 at 06:30
  • resetForm is available at provided reference. – Somo S. Sep 25 '17 at 22:26
  • `resetForm()` is only available on the `ngForm` object. If calls the `reset()` function on the `FormGroup` object nested in the `ngForm` object. – Grungondola May 11 '18 at 17:24
  • I use `.resetForm()` to reset forms. Any idea how to reset form except one form feild? The method `supportForm.controls['name'].reset();` resets the perticular form field but doesn't get rid of the form error messages left behind after reset. – Sushmit Sagar Mar 28 '19 at 09:24
25

For Angular 2 Final, we now have a new API that cleanly resets the form:

@Component({...})
class App {

    form: FormGroup;
     ...
    reset() {
       this.form.reset();
   }
}

This API not only resets the form values, but also sets the form field states back to ng-pristine and ng-untouched.

Angular University
  • 42,341
  • 15
  • 74
  • 81
  • angular2 final what do you mean by this ? angular2 is in RC right now i think is't it ? also throwing error `form.reset()` is not a funcation. – Pardeep Jain Aug 22 '16 at 11:32
  • @PardeepJain RC5 is released few days ago and .reset() is present there but because RC5 has some changes, trying it out with existing project might be difficult/breaking. Even if your code is fine for RC5, some external modules you use may not be. I'd recommend you try it out on a fresh project if you wish so. – Bogac Aug 25 '16 at 07:57
  • opps i am trying the same using RC4, my mistake sorry – Pardeep Jain Aug 25 '16 at 08:48
  • 4
    Unfortunately, if you have validators, the fields "ng-invalid" class is kept after the form is reset (still happens in Angular 4.1.0-rc.0) – MrCroft Apr 26 '17 at 14:04
  • why I am I getting form as undefined in "this.form.reset()"? Also, when I do
    , I get this error - Can't bind to 'formGroup' since it isn't a known property of 'form'.
    – shanti Oct 05 '17 at 09:44
8

If you call only reset() function, the form controls will not set to pristine state. android.io docs have a solution for this issue.

component.ts

  active = true; 

  resetForm() {
      this.form.reset();
      this.active = false;
      setTimeout(() => this.active = true, 0);
  }

component.html

<form *ngIf="active">
asimolmez
  • 700
  • 8
  • 14
6

When I was going through the Angular basics guide on forms, and hit the resetting of forms section, I was very much left in surprise when I read the following in regards to the solution they give.

This is a temporary workaround while we await a proper form reset feature.

I personally haven't tested if the workaround they provided works (i assume it does), but I believe it is not neat, and that there must be a better way to go about the issue.

According to the FormGroup API (which is marked as stable) there already is a 'reset' method.

I tried the following. In my template.html file i had

<form (ngSubmit)="register(); registrationForm.reset();" #registrationForm="ngForm">
    ...
</form>

Notice that in the form element, I've initialised a template reference variable 'registrationForm' and initialized it to the ngForm Directive, which "governs the form as a whole". This gave me access to the methods and attributes of the governing FormGroup, including the reset() method.

Binding this method call to the ngSubmit event as show above reset the form (including pristine, dirty, model states etc) after the register() method is completed. For a demo this is ok, however it isn't very helpful for real world applications.

Imagine the register() method performs a call to the server. We want to reset the form when we know that the server responded back that everything is OK. Updating the code to the following caters for this scenario.

In my template.html file :

<form (ngSubmit)="register(registrationForm);" #registrationForm="ngForm">
    ...
</form>

And in my component.ts file :

@Component({
  ...
})
export class RegistrationComponent {
  register(form: FormGroup) {

   ...

   // Somewhere within the asynchronous call resolve function
   form.reset();
  }
}

Passing the 'registrationForm' reference to the method would allow us to call the reset method at the point of execution that we want to.

Hope this helps you in any way. :)

Note: This approach is based on Angular 2.0.0-rc.5

JeanPaul A.
  • 3,613
  • 1
  • 20
  • 29
  • It seems that the latter way I mentioned is how it is employed. I just encountered it in the template syntax guide. https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngform-and-template-reference-variables – JeanPaul A. Aug 23 '16 at 09:03
6

I don't know if I'm on the right path, but I got it working on ng 2.4.8 with the following form/submit tags:

<form #heroForm="ngForm" (ngSubmit)="add(newHero); heroForm.reset()">
<!-- place your input stuff here -->
<button type="submit" class="btn btn-default" [disabled]="!heroForm.valid">Add hero</button>

Seems to do the trick and sets the form's fields to "pristine" again.

Christof Kälin
  • 1,384
  • 2
  • 17
  • 26
  • This is the only thing that worked for me since I'm not referring to the form object in the component code at all. I hate the idea of assigning `ngSubmit` to two separate commands but I guess that's how they do it. ¯\\_(ツ)_/¯ – Jason Swett Apr 27 '17 at 10:32
1

I'm using reactive forms in angular 4 and this approach works for me:

    this.profileEditForm.reset(this.profileEditForm.value);

see reset the form flags in the Fundamentals doc

1
form: NgForm;

form.reset()

This didn't work for me. It cleared the values but the controls raised an error.

But what worked for me was creating a hidden reset button and clicking the button when we want to clear the form.

<button class="d-none" type="reset" #btnReset>Reset</button>

And on the component, define the ViewChild and reference it in code.

@ViewChild('btnReset') btnReset: ElementRef<HTMLElement>;

Use this to reset the form.

this.btnReset.nativeElement.click();

Notice that the class d-none sets display: none; on the button.

Minasie Shibeshi
  • 390
  • 3
  • 16
0

I used in similar case the answer from Günter Zöchbauer, and it was perfect to me, moving the form creation to a function and calling it from ngOnInit().

For illustration, that's how I made it, including the fields initialization:

ngOnInit() {
    // initializing the form model here
    this.createForm();
}

createForm() {
    let EMAIL_REGEXP = /^[^@]+@([^@\.]+\.)+[^@\.]+$/i; // here just to add something more, useful too

    this.userForm = new FormGroup({
        name: new FormControl('', [Validators.required, Validators.minLength(3)]),
        city: new FormControl(''),
        email: new FormControl(null, Validators.pattern(EMAIL_REGEXP))
    });

    this.initializeFormValues();
}

initializeFormValues() {
    const people = {
        name: '',
        city: 'Rio de Janeiro',  // Only for demonstration
        email: ''
    };
    (<FormGroup>this.userForm).setValue(people, { onlySelf: true });
}

resetForm() {
    this.createForm();
    this.submitted = false;
}

I added a button to the form for a smart reset (with the fields initialization):

In the HTML file (or inline template):

<button type="button" [disabled]="userForm.pristine" (click)="resetForm()">Reset</button>

After loading the form at first time or after clicking the reset button we have the following status:

FORM pristine: true 
FORM valid: false (because I have required a field) 
FORM submitted: false
Name pristine: true
City pristine: true
Email pristine: true

And all the field initializations that a simple form.reset() doesn't make for us! :-)

joaumg
  • 1,238
  • 1
  • 12
  • 27
0

Please use The following format, its working perfectly for me..i have checked lot ways but this works perfectly.<form (ngSubmit)="mySubmitHandler(); myNgForm.resetForm()" #myNgForm="ngForm"> .... </form>

0

if anybody wants to clear out only a particular form control one can use

formSubmit(){
this.formName.patchValue({
         formControlName:''
          //or if one wants to change formControl to a different value on submit
          formControlName:'form value after submission'     
    });
}
0

Now NgForm supports two methods: .reset() vs .resetForm() the latter also changes the submit state of the form to false reverting form and its controls to initial states.