Deshabilite el clic fuera del área de diálogo de material angular para cerrar el diálogo (con la versión angular 4.0+)

103

Actualmente estoy trabajando en la página de restablecimiento de contraseña de un proyecto de Angular 4. Estamos usando Material angular para crear el cuadro de diálogo, sin embargo, cuando el cliente hace clic fuera del cuadro de diálogo, se cerrará automáticamente. ¿Hay alguna manera de evitar que el diálogo se cierre hasta que nuestro lado del código llame a la función "cerrar"? ¿O cómo debería crear un modal que no se pueda cerrar ?

Terry Zhang
fuente

Respuestas:

267

Hay dos maneras de hacerlo.

  1. En el método que abre el cuadro de diálogo, pase la siguiente opción de configuración disableClosecomo segundo parámetro MatDialog#open()y configúrelo en true:

    export class AppComponent {
      constructor(private dialog: MatDialog){}
      openDialog() {
        this.dialog.open(DialogComponent, { disableClose: true });
      }
    }
    
  2. Alternativamente, hágalo en el propio componente de diálogo.

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

Esto es lo que busca:

Propiedad <code> disableClose </code> en material.angular.io

Y aquí hay una demostración de Stackblitz


Otros casos de uso

Aquí hay algunos otros casos de uso y fragmentos de código de cómo implementarlos.

Permitir esccerrar el cuadro de diálogo pero no permitir hacer clic en el fondo para cerrar el cuadro de diálogo

Como dijo @MarcBrazeau en el comentario debajo de mi respuesta, puede permitir que la escclave cierre el modal pero aún no permitir hacer clic fuera del modal. Utilice este código en su componente de diálogo:

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

}

Evita esccerrar el cuadro de diálogo pero permite hacer clic en el fondo para cerrar

PD: esta es una respuesta que se originó a partir de esta respuesta , donde la demostración se basó en esta respuesta.

Para evitar que la esctecla cierre el cuadro de diálogo pero permita que se cierre el clic en el fondo, he adaptado la respuesta de Marc, además de usar MatDialogRef#backdropClickpara escuchar eventos de clic en el fondo.

Inicialmente, el diálogo tendrá la opción de configuración disableCloseestablecida como true. Esto asegura que la escpulsación de la tecla, así como hacer clic en el fondo no hará que el diálogo se cierre.

Luego, suscríbase al MatDialogRef#backdropClickmétodo (que se emite cuando se hace clic en el fondo y regresa como a MouseEvent).

De todos modos, suficiente charla técnica. Aquí está el código:

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

  // ...
}

Alternativamente, esto se puede hacer en el componente de diálogo:

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();
    })
  }
}
Edric
fuente
5
Me parece molesto que tengas que deshabilitar "escapar y hacer clic fuera". Para evitar esto:@HostListener('window:keyup.esc') onKeyUp() { this.dialogRef.close(); }
Marc Brazeau
@MarcBrazeau He agregado tu comentario a mi respuesta.
Edric
1
Una advertencia para las personas que utilizan campos de entrada con autocompletar. El uso de HostListener cierra el diálogo cuando cierra la lista de autocompletar.
Jompis
Gracias por su ayuda
Rafael Moura
1
También necesitaría manejar la cancelación de la suscripción desde el telón de fondo Haga clic en Observable, de lo contrario, introducirá una pérdida de memoria.
sombrío
3

¿Qué tal jugar con estas dos propiedades?

disableClose: boolean: si el usuario puede usar escape o hacer clic en el fondo para cerrar el modal.

hasBackdrop: boolean: si el cuadro de diálogo tiene un fondo.

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

alansiqueira27
fuente
establecer hasBackdrop en falso elimina el ennegrecimiento del área fuera del cuadro de diálogo
Mohit Atray
Trabajado con Angular 9. 'hasBackdrop' no permite al usuario interactuar con otros elementos externos. disableClose no permite al usuario cerrar el cuadro de diálogo con un clic externo o una tecla de escape.
Naveen Kumar V