Disable click outside of angular material dialog area to close the dialog (With Angular Version 4.0+)

162,516

Solution 1

There are two ways to do it.

  1. In the method that opens the dialog, pass in the following configuration option disableClose as the second parameter in MatDialog#open() and set it to true:

    export class AppComponent {
      constructor(private dialog: MatDialog){}
      openDialog() {
        this.dialog.open(DialogComponent, { disableClose: true });
      }
    }
    
  2. Alternatively, do it in the dialog component itself.

    export class DialogComponent {
      constructor(private dialogRef: MatDialogRef<DialogComponent>){
        dialogRef.disableClose = true;
      }
    }
    

Here's what you're looking for:

<code>disableClose</code> property in material.angular.io

And here's a Stackblitz demo


Other use cases

Here's some other use cases and code snippets of how to implement them.

Allow esc to close the dialog but disallow clicking on the backdrop to close the dialog

As what @MarcBrazeau said in the comment below my answer, you can allow the esc key to close the modal but still disallow clicking outside the modal. Use this code on your dialog component:

import { Component, OnInit, HostListener } from '@angular/core';
import { MatDialogRef } from '@angular/material';
@Component({
  selector: 'app-third-dialog',
  templateUrl: './third-dialog.component.html'
})
export class ThirdDialogComponent {
  constructor(private dialogRef: MatDialogRef<ThirdDialogComponent>) {      
}
  @HostListener('window:keyup.esc') onKeyUp() {
    this.dialogRef.close();
  }

}

Prevent esc from closing the dialog but allow clicking on the backdrop to close

P.S. This is an answer which originated from this answer, where the demo was based on this answer.

To prevent the esc key from closing the dialog but allow clicking on the backdrop to close, I've adapted Marc's answer, as well as using MatDialogRef#backdropClick to listen for click events to the backdrop.

Initially, the dialog will have the configuration option disableClose set as true. This ensures that the esc keypress, as well as clicking on the backdrop will not cause the dialog to close.

Afterwards, subscribe to the MatDialogRef#backdropClick method (which emits when the backdrop gets clicked and returns as a MouseEvent).

Anyways, enough technical talk. Here's the code:

openDialog() {
  let dialogRef = this.dialog.open(DialogComponent, { disableClose: true });
  /*
     Subscribe to events emitted when the backdrop is clicked
     NOTE: Since we won't actually be using the `MouseEvent` event, we'll just use an underscore here
     See https://stackoverflow.com/a/41086381 for more info
  */
  dialogRef.backdropClick().subscribe(() => {
    // Close the dialog
    dialogRef.close();
  })

  // ...
}

Alternatively, this can be done in the dialog component:

export class DialogComponent {
  constructor(private dialogRef: MatDialogRef<DialogComponent>) {
    dialogRef.disableClose = true;
    /*
      Subscribe to events emitted when the backdrop is clicked
      NOTE: Since we won't actually be using the `MouseEvent` event, we'll just use an underscore here
      See https://stackoverflow.com/a/41086381 for more info
    */
    dialogRef.backdropClick().subscribe(() => {
      // Close the dialog
      dialogRef.close();
    })
  }
}

Solution 2

How about playing with these two properties?

disableClose: boolean - Whether the user can use escape or clicking on the backdrop to close the modal.

hasBackdrop: boolean - Whether the dialog has a backdrop.

https://material.angular.io/components/dialog/api

Solution 3

Add

[config]="{backdrop: 'static'}"

to the modal code.

Share:
162,516

Related videos on Youtube

Terry Zhang
Author by

Terry Zhang

I am a command-line fan!

Updated on May 28, 2021

Comments

  • Terry Zhang
    Terry Zhang almost 3 years

    I am currently working on password reset page of an Angular 4 project. We are using Angular Material to create the dialog, however, when the client clicks out of the dialog, it will close automatically. Is there a way to avoid the dialog close until our code side call "close" function? Or how should I create an unclosable modal?

  • Marc Brazeau
    Marc Brazeau over 6 years
    I do find it annoying that you have to disable both "escape and clicking outside". To get around this: @HostListener('window:keyup.esc') onKeyUp() { this.dialogRef.close(); }
  • Edric
    Edric about 6 years
    @MarcBrazeau I've added your comment to my answer.
  • Jompis
    Jompis almost 5 years
    A warning for people using input fields with autocomplete. Using the HostListener closes the dialog when you close the auto-complete list.
  • Rafael Moura
    Rafael Moura over 4 years
    Thanks for your help
  • grim_i_am
    grim_i_am over 4 years
    You would also need to handle unsubscribing from the backdropClick Observable otherwise you'll introduce a memory leak.
  • Mohit Atray
    Mohit Atray over 4 years
    setting hasBackdrop to false removes the blackening of area outside the dialog
  • Naveen Kumar V
    Naveen Kumar V over 3 years
    Worked with Angular 9. 'hasBackdrop' does not let the user to interact with other outside elements. disableClose does not allow the user to close the dialog with outside click or escape key.
  • fabio984
    fabio984 about 3 years
    I added @HostListener('window:keyup.escape') but I press ESC and it closes all modals... Can I bind the listner to the latest opened modal? I just want close one modal each time with ESC. DisableClose is set to true.