Resetting a form in Angular 2 after submit
AngularAngular2 FormsAngular Problem Overview
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);
}
}
}
Angular Solutions
Solution 1 - Angular
>= 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);
}
);
}
}
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();
}
}
Solution 2 - Angular
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
Solution 3 - Angular
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
.
Solution 4 - Angular
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">
Solution 5 - Angular
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
Solution 6 - Angular
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.
Solution 7 - Angular
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
Solution 8 - Angular
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! :-)
Solution 9 - Angular
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>
Solution 10 - Angular
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'
});
}
Solution 11 - Angular
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.
Solution 12 - Angular
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.