问题
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);
}
}
}
回答1:
>= 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
回答2:
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
回答3:
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
.
回答4:
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
回答5:
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.
回答6:
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">
回答7:
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! :-)
回答8:
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
回答9:
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>
回答10:
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'
});
}
来源:https://stackoverflow.com/questions/36655922/resetting-a-form-in-angular-2-after-submit