Angular NgBootstrap Modal How to listen to backdrop click

815 views Asked by At

My use case would be, when I open the modal, a form will appear, while the user fill up the form, the user suddenly click on the backdrop, so the default behavior would be, the modal would be closed.

However, I want to listen on that event because I want to show a modal when the user accidentally click on backdrop which tells that "DO YOU WANT TO SAVE CHANGES?" something like that which generally tells that the form is touched and dirty.

I've read the documentation, and other sources, which tells on the shows something like this

modalRef.result.then((data) => {
      // on close
    },
    (error) => {
      // on error/dismiss
});

How do I pass or know that when I clicked on backdrop, the modal which holds the form has been marked touched or dirty so that I could display another modal informing the user for confirmation something like "YOU HAVE UNSAVED CHANGES"

I'm looking for like in Angular Material Dialog they have something like afterClosed subscribe method.

Thanks in advance. Please tell if I miss some code or details to provide.

2

There are 2 answers

0
Chris Barr On

See the code for the very firs example in the docs: https://ng-bootstrap.github.io/#/components/modal/examples

import { ModalDismissReasons, NgbDatepickerModule, NgbModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'ngbd-modal-basic',
  standalone: true,
  imports: [NgbDatepickerModule],
  templateUrl: './modal-basic.html',
})
export class NgbdModalBasic {
  closeResult = '';

  constructor(private modalService: NgbModal) {}

  open(content) {
    this.modalService.open(content, { ariaLabelledBy: 'modal-basic-title' }).result.then(
      (result) => {
        this.closeResult = `Closed with: ${result}`;
      },
      (reason) => {
        this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
      },
    );
  }

  private getDismissReason(reason: any): string {
    if (reason === ModalDismissReasons.ESC) {
      return 'by pressing ESC';
    } else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
      return 'by clicking on a backdrop';
    } else {
      return `with: ${reason}`;
    }
  }
}
<ng-template #content let-modal>
    <div class="modal-header">
        <h4 class="modal-title" id="modal-basic-title">Profile update</h4>
        <button type="button" class="btn-close" aria-label="Close" (click)="modal.dismiss('Cross click')"></button>
    </div>
    <div class="modal-body">
        Stuff can go here
    </div>
    <div class="modal-footer">
        <button type="button" class="btn btn-outline-dark" (click)="modal.close('Save click')">Save</button>
    </div>
</ng-template>

<button class="btn btn-lg btn-outline-primary" (click)="open(content)">Launch demo modal</button>

<hr />

<pre>{{ closeResult }}</pre>
0
alvinydev On

@Aakash Garg Thanks mate.

addOpenEntry(): void {
    const openEntryRef = this.modalService.open(OpenEntryComponent, {
      size: "lg",
      beforeDismiss: async () => {
        const dirtyForm = openEntryRef.componentInstance.form1.dirty;
        if (dirtyForm) {
          return await this.confirmationDialog();
        }
        return true;
      }
    })
  }




async confirmationDialog() {
    let payload = {
      dialog_title: "Unsaved Changes",
      dialog_msg: "You have unsaved changes. Are you sure you want to discard all your changes?",
    }

    let modalRef = this.modalService.open(ConfirmDialogComponent)
    modalRef.componentInstance.data = payload;

    let result = await modalRef.result
    return result;
  }

The above code is what I have ended up writing and meet my use case. Thanks again!