question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItΒ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ngSubmit should trigger after Asynchronous Validation completes

See original GitHub issue

πŸš€ feature request

Relevant Package

This feature request is for @angular/forms

Specifically, 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();
    }
}

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:21
  • Comments:21 (5 by maintainers)

github_iconTop GitHub Comments

5reactions
sasunstepanyan777commented, Feb 18, 2022

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

1reaction
dylhunncommented, Feb 3, 2022

for most use-cases having a flag β€˜waitForAsyncValidation’ which defaults to true would be the way to go.

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Reactive Angular form to wait for async validator complete on ...
Angular doesn't wait for async validators to complete before firing ngSubmit . So the form may be invalid if the validators have notΒ ......
Read more >
Angular async validator to validate an input field ... - Trung Vo
Angular doesn't wait for async validators to complete before firing ngSubmit. So the form may be invalid if the validators have not resolved....
Read more >
Angular Custom Form Validators: Complete Guide
In this post, you will learn everything that you need to know in order to implement your own custom form validators, including both...
Read more >
NgForm - Angular
Returns whether the form submission has been triggered. ... DOM validation UI with Angular forms, you can add the ngNativeValidate attribute to the...
Read more >
Form Testing in Angular | Simple Web Learning
Like all other component testing, we can validate the HTML ... then we trigger the ngSubmit event on the form element and test...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found