title: Disabling submit button onSubmit in Angular 9 web app so multiple form submissions do not occur
body: <p>I have an issue with my Angular 9 application sending multiple form submissions when a user clicks the submit button multiple times, I would like to disable the submit button once it has validated and submission is triggered up until the form has submitted and reset, I have designed the form to use modals for when a form is accepted or denied but quite often a user will click multiple times during loading, I have added a disabledSubmitButton boolean but this completely disables the submit button - ruining the user experience by also disabling the incorrect form fields modal. Any help would be much appreciated!</p>
  
  <p>Here is my contact form HTML</p>
  
  <pre><code>&lt;div class="container section-title-hero text-center msf"&gt;
    &lt;h1&gt;Contact Us&lt;/h1&gt;
  &lt;/div&gt;
  
  &lt;div class="container-fluid"&gt;
    &lt;div class="container"&gt;&lt;/div&gt;
  &lt;/div&gt;
  
  &lt;div class="container-fluid"&gt;
    &lt;div class="container"&gt;
  
      &lt;mdb-card class="mt-3 mb-3"&gt;
  
        &lt;mdb-card-body class="px-lg-5 pt-0"&gt;
          &lt;div class="row"&gt;
            &lt;div class=" msf msfc col mt-3"&gt;
              &lt;h5&gt;Send us a message&lt;/h5&gt;
            &lt;/div&gt;
          &lt;/div&gt;
  
          &lt;form class="text-center" style="color: #757575;" [formGroup]="contactForm" (ngSubmit)="onSubmit()"&gt;
            &lt;div style="color: #030A8c !important; padding-bottom: 1em;" class="md-form mt-3"&gt;
              &lt;input type="text" formControlName="contactFormName" id="materialContactFormName" class="form-control"
                mdbInput mdbValidate /&gt;
              &lt;label for="materialContactFormName"&gt;Name&lt;/label&gt;
              &lt;mdb-error *ngIf="contactFormName.invalid &amp;&amp; (contactFormName.dirty || contactFormName.touched)"&gt;&lt;i
                  class="fa fa-times" aria-hidden="true"&gt;&lt;/i&gt;
                Please
                enter your name&lt;/mdb-error&gt;
              &lt;mdb-success *ngIf="contactFormName.valid &amp;&amp; (contactFormName.dirty || contactFormName.touched)"&gt;&lt;i
                  class=" fa fa-check" aria-hidden="true"&gt;&lt;/i&gt;
              &lt;/mdb-success&gt;
            &lt;/div&gt;
  
            &lt;div style="color: #030A8c !important; padding-bottom: 1em;" class="md-form"&gt;
              &lt;input type="email" formControlName="contactFormEmail" id="materialContactFormEmail" class="form-control"
                mdbInput mdbValidate /&gt;
              &lt;label for="materialContactFormEmail"&gt;E-mail&lt;/label&gt;
              &lt;mdb-error *ngIf="contactFormEmail.invalid &amp;&amp; (contactFormEmail.dirty || contactFormEmail.touched)"&gt;&lt;i
                  class="fa fa-times" aria-hidden="true"&gt;&lt;/i&gt;
                Please
                enter your email&lt;/mdb-error&gt;
              &lt;mdb-success *ngIf="contactFormEmail.valid &amp;&amp; (contactFormEmail.dirty || contactFormEmail.touched)"&gt;&lt;i
                  class=" fa fa-check" aria-hidden="true"&gt;&lt;/i&gt;
              &lt;/mdb-success&gt;
            &lt;/div&gt;
  
  
  
  
            &lt;div style="color: #030A8c !important; padding-bottom: 1em;" class="md-form"&gt;
              &lt;input type="text" formControlName="contactFormSubjects" id="materialContactFormSubjects"
                class="form-control" mdbInput mdbValidate /&gt;
              &lt;label for="materialContactFormSubjects"&gt;Subject&lt;/label&gt;
              &lt;mdb-error
                *ngIf="contactFormSubjects.invalid &amp;&amp; (contactFormSubjects.dirty || contactFormSubjects.touched)"&gt;
                &lt;i class="fa fa-times" aria-hidden="true"&gt;&lt;/i&gt;
                Please enter a subject&lt;/mdb-error&gt;
              &lt;mdb-success
                *ngIf="contactFormSubjects.valid &amp;&amp; (contactFormSubjects.dirty || contactFormSubjects.touched)"&gt;
                &lt;i class=" fa fa-check" aria-hidden="true"&gt;&lt;/i&gt;&lt;/mdb-success&gt;
            &lt;/div&gt;
  
  
            &lt;div style="color: #030A8c !important; padding-bottom: 1em;" class="md-form"&gt;
              &lt;textarea type="text" formControlName="contactFormMessage" id="materialContactFormMessage"
                class="form-control md-textarea" mdbInput mdbValidate&gt;&lt;/textarea&gt;
              &lt;label for="materialContactFormMessage"&gt;Message&lt;/label&gt;
              &lt;mdb-error *ngIf="contactFormMessage.invalid &amp;&amp; (contactFormMessage.dirty || contactFormMessage.touched)"&gt;
                &lt;i class="fa fa-times" aria-hidden="true"&gt;&lt;/i&gt;
                Please enter a message&lt;/mdb-error&gt;
              &lt;mdb-success *ngIf="contactFormMessage.valid &amp;&amp; (contactFormMessage.dirty || contactFormMessage.touched)"&gt;
                &lt;i class=" fa fa-check" aria-hidden="true"&gt;&lt;/i&gt;&lt;/mdb-success&gt;
            &lt;/div&gt;
  
            &lt;!-- &lt;div class="row"&gt;
              &lt;div class="col-md-6 mx-auto d-flex justify-content-center"&gt;
                &lt;div class="md-form"&gt;
                  &lt;mdb-checkbox mdbValidate formControlName="contactFormCopy"&gt;Send me a copy of this message
                  &lt;/mdb-checkbox&gt;
                  &lt;mdb-error *ngIf="copy.invalid &amp;&amp; (copy.dirty || copy.touched)"&gt;Input invalid&lt;/mdb-error&gt;
                  &lt;mdb-success *ngIf="copy.valid &amp;&amp; (copy.dirty || copy.touched)"&gt;Input valid&lt;/mdb-success&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt; --&gt;
            &lt;div class="row"&gt;
              &lt;div class="col"&gt;
                &lt;button mdbBtn (click)="openModal()" color="info" outline="true" rounded="true"
                  class="z-depth-0 my-4 waves-effect" mdbWavesEffect type="submit" [disabled]="disabledSubmitButton"&gt;
                  Send
                &lt;/button&gt;
              &lt;/div&gt;
            &lt;/div&gt;
  
          &lt;/form&gt;
  
  
        &lt;/mdb-card-body&gt;
  
      &lt;/mdb-card&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;!--  End Contact Section --&gt;
  
  &lt;app-branch-locations&gt;&lt;/app-branch-locations&gt;
  &lt;!-- Start Branch Locations Section --&gt;
  
  
  
  &lt;div class="container"&gt;
    &lt;hr&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>And here is the contact form typescript</p>
  
  <pre><code>import { ConnectionService } from '../../connection.service';
  import { FormGroup, FormBuilder, Validators } from '@angular/forms';
  import { Component, OnInit, HostListener } from '@angular/core';
  
  // Modals
  import { ContactmailmodalComponent } from '../../views/modals/contact/contactmailmodal/contactmailmodal.component';
  import { ContactvalidationmodalComponent } from '../../views/modals/contact/contactvalidationmodal/contactvalidationmodal.component';
  
  import { MDBModalRef, MDBModalService } from 'ng-uikit-pro-standard';
  
  @Component({
    selector: 'app-contact',
    templateUrl: './contact.component.html',
    styleUrls: ['./contact.component.scss']
  })
  export class ContactComponent implements OnInit {
  
  
  
  
  
    disabledSubmitButton: boolean = true;
    // Contact Form
    contactForm: FormGroup;
  // disabledSubmitButton: boolean = true;
  optionsSelect: Array&lt;any&gt;;
  
  
  modalRef: MDBModalRef;
    constructor(private modalService: MDBModalService, fb: FormBuilder, private connectionService: ConnectionService) {
  
    this.contactForm = fb.group({
      'contactFormName': ['', Validators.required],
      'contactFormEmail': ['', Validators.compose([Validators.required, Validators.email])],
      'contactFormSubjects': ['', Validators.required],
      'contactFormMessage': ['', Validators.required],
      // 'contactFormCopy': ['', Validators.requiredTrue],
      });
    }
  
    ngOnInit() {
  
    this.optionsSelect = [
      { value: 'Feedback', label: 'Feedback' },
      { value: 'Report a bug', label: 'Report a bug' },
      { value: 'Feature request', label: 'Feature request' },
      { value: 'Other stuff', label: 'Other stuff' },
      ];
    }
  
    get contactFormName() {
      return this.contactForm.get('contactFormName');
    }
    get contactFormEmail() {
      return this.contactForm.get('contactFormEmail');
    }
    get contactFormSubjects() {
      return this.contactForm.get('contactFormSubjects');
    }
    get contactFormMessage() {
      return this.contactForm.get('contactFormMessage');
    }
    // get copy() {
    //   return this.contactForm.get('contactFormCopy');
    // }
  
    onSubmit() {
      if (this.contactForm.valid) {
        console.log("form submitted");
  
  
        this.connectionService.sendMessage(this.contactForm.value).subscribe(
  
          () =&gt; {
            this.disabledSubmitButton = true;
            this.modalRef = this.modalService.show(ContactmailmodalComponent);
  
  
          },
  
          (error) =&gt; {
            console.log("Error", error);
          }
  
        );
      } else {
        // validate all form fields
        this.modalRef = this.modalService.show(
          ContactvalidationmodalComponent
        );
        Object.keys(this.contactForm.controls).forEach((field) =&gt; {
          // {1}
          const control = this.contactForm.get(field); // {2}
          control.markAsTouched({ onlySelf: true }); // {3}
        });
      }
    }
    openModal() {
  
    }
  }
  
  </code></pre>
  
  <p>Thanks in advance!</p>