angular: ngSubmit should trigger after Asynchronous Validation completes
đ feature request
Relevant Package
This feature request is for @angular/formsSpecifically, Reactive Forms
Description
**in Template**
<form [formGroup]="myFormGroup" (ngSubmit)="mFG_submit()"></form>
**In Component**
mFG_submit() {
if (!myFormGroup.valid)
return;
//logic that will run if and only if the entire form is valid after both
sync and async validators have finished executing
}
The problem with the above code is that if myFormGroup has any controls with asynchronous validators, then ngSubmit is triggered after the async validators have started executing, but before they have finished executing. As as result, when the âifâ gate inside mFG_submit() is hit, it returns immediately, because the form status is âPENDINGâ. As a result, even if the asynchronous validator returns true, i,e, the control is valid, the submission logic is never executed.
Describe the solution youâd like
One solution is to check on every submit if the form status is âPENDINGâ, and then listen to status changes, and emit ngSubmit again, the moment status changes. I would like to have such behaviour provided by the framework Currently, I use this directive
@Directive({
selector: 'form[formGroup]'
})
export class ResubmitIfPendingDirective {
constructor(
private fgd: FormGroupDirective
) {
this.subscriptions.add(this.resubmission_sub);
}
private subscriptions: Subscription = new Subscription();
private resubmission_sub: Subscription = new Subscription();
ngOnInit() {
//listen to ngSubmit of the form
this.subscriptions.add(this.fgd.ngSubmit.subscribe(() => {
//if you are already subscribed to status changes, unsubscribe
this.subscriptions.remove(this.resubmission_sub);
this.resubmission_sub.unsubscribe();
//if your form is PENDING when submitted, subscribe to status changes
if (this.fgd.control.pending) {
this.resubmission_sub = this.fgd.control.statusChanges
.pipe(
//don't do anything if new emitted status is PENDING
filter(() => !this.fgd.control.pending),
//status no longer PENDING, time to resubmit
//and stop observing statusChanges
first()
// above 2 pipes can be combined, I separated for clarity
// first(() => !this.fgd.control.pending)
).subscribe(() => this.fgd.ngSubmit.emit());
this.subscriptions.add(this.resubmission_sub)
//since the validation has already been run,
//and there have no change in the values of the controls,
//the status of this follow-up ngSubmit will either emit
//VALID or INVALID
//therefore, the ngSubmit we emit will simply
//unsubscribe resubmission_sub
//and never re-enter this if() block
//Thus, No infinite loop of submits
}
}));
}
ngOnDestroy() {
//stop listening to ngSubmit and status changes
this.subscriptions.unsubscribe();
}
}
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 24
- Comments: 22 (5 by maintainers)
Links to this issue
Commits related to this issue
- fix(forms): add an input property to form directives that makes ngSubmit wait for async validation to complete before it emits fix #31021 Before this change, ngSubmit would emit immediately after ru... — committed to DibyodyutiMondal/angular by DibyodyutiMondal 2 years ago
- fix(forms): add an input property to form directives that makes ngSubmit wait for async validation to complete before it emits fix #31021 Before this change, ngSubmit would emit immediately after ru... — committed to DibyodyutiMondal/angular by DibyodyutiMondal 2 years ago
- fix(forms): add an input property to form directives that makes ngSubmit wait for async validation to complete before it emits fix #31021 Before this change, ngSubmit would emit immediately after ru... — committed to DibyodyutiMondal/angular by DibyodyutiMondal 2 years ago
- fix(forms): add an input property to form directives that makes ngSubmit wait for async validation to complete before it emits fix #31021 Before this change, ngSubmit would emit immediately after ru... — committed to DibyodyutiMondal/angular by DibyodyutiMondal 2 years ago
- feat(forms): add an input property to form directives that makes ngSubmit wait for async validation to complete before it emits fix #31021 Before this change, ngSubmit would emit immediately after r... — committed to DibyodyutiMondal/angular by DibyodyutiMondal 2 years ago
I think we should add that flag as an option into formBuilder.group like:
form: FormGroup = this.formBuilder.group({ ...control }, { waitForAsyncValidation: true });
and have a method in FormGroup to change this flag
I agree that this is the easiest solution. However, weâd need to default to
false
to avoid making breaking changes. Then we could add a migration and flip the default in a future framework version.Would you be comfortable putting together a PR to fix this? Iâd like to fix it, but donât have the bandwidth right now. Happy to review and merge it though.
Yes, that is exactly the situation that made me pursue this route. XD
PS: Pls forgive me for pressing the wrong button. đ
I have also encountered this issue. It seems that if you have a long form that itâs not so much of an issue - however if youâre using a reactive form for a simple login, thatâs when it becomes a problem. Because a user presses enter to login after they type their password. This triggers the validation, but because the state is âPENDINGâ, the submission cannot go ahead. The solution is to set up a complex observable that waits until the status is valid etcâŚ
A cleaner solution would be much appreciated.