Wyłącz kliknięcie poza obszarem okna dialogowego materiału kątowego, aby zamknąć okno (z wersją Angular 4.0+)

106

Obecnie pracuję nad stroną resetowania hasła w projekcie Angular 4. Używamy Angular Material do tworzenia okna dialogowego, jednak gdy klient kliknie okno dialogowe, zamknie się ono automatycznie. Czy istnieje sposób na uniknięcie zamknięcia okna dialogowego przed wywołaniem funkcji „close” po stronie kodu? Albo jak utworzyć niezamykany modal?

Terry Zhang
źródło

Odpowiedzi:

278

Można to zrobić na dwa sposoby.

  1. W metodzie, która otwiera okno dialogowe, podaj następującą opcję konfiguracyjną disableClosejako drugi parametr programu MatDialog#open()i ustaw ją na true:

    export class AppComponent {
      constructor(private dialog: MatDialog){}
      openDialog() {
        this.dialog.open(DialogComponent, { disableClose: true });
      }
    }
    
  2. Alternatywnie zrób to w samym komponencie okna dialogowego.

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

Oto, czego szukasz:

Właściwość <code> disableClose </code> w material.angular.io

A oto demo Stackblitz


Inne przypadki użycia

Oto kilka innych przypadków użycia i fragmenty kodu pokazujące, jak je zaimplementować.

Pozwól esczamknąć okno dialogowe, ale nie zezwalaj na klikanie tła w celu zamknięcia okna

Jak powiedział @MarcBrazeau w komentarzu pod moją odpowiedzią, możesz pozwolić escklawiszowi na zamknięcie modalu, ale nadal nie zezwalaj na klikanie poza modalem. Użyj tego kodu w komponencie okna dialogowego:

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

}

Zapobiegaj esczamykaniu okna, ale pozwól na kliknięcie tła, aby je zamknąć

PS To jest odpowiedź, która pochodzi z tej odpowiedzi , gdzie demo było oparte na tej odpowiedzi.

Aby escklawisz nie zamykał okna, ale pozwalał na kliknięcie tła w celu zamknięcia, dostosowałem odpowiedź Marca, a także użycie funkcji MatDialogRef#backdropClicknasłuchiwania kliknięć do tła.

Początkowo w oknie dialogowym opcja konfiguracji będzie disableCloseustawiona jako true. Gwarantuje to, że escnaciśnięcie klawisza, a także kliknięcie tła nie spowoduje zamknięcia okna dialogowego.

Następnie zasubskrybuj MatDialogRef#backdropClickmetodę (która jest emitowana po kliknięciu tła i powraca jako MouseEvent).

Tak czy inaczej, dość technicznych rozmów. Oto kod:

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

  // ...
}

Alternatywnie można to zrobić w komponencie okna dialogowego:

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
źródło
5
To denerwujące, że musisz wyłączyć zarówno opcję „ucieczki, jak i klikania na zewnątrz”. Aby obejść ten problem:@HostListener('window:keyup.esc') onKeyUp() { this.dialogRef.close(); }
Marc Brazeau
@MarcBrazeau Dodałem Twój komentarz do mojej odpowiedzi.
Edric
1
Ostrzeżenie dla osób używających pól wejściowych z autouzupełnianiem. Użycie HostListener zamyka okno dialogowe po zamknięciu listy autouzupełniania.
Jompis
Dzięki za pomoc
Rafael Moura
1
Będziesz również musiał obsłużyć anulowanie subskrypcji z backdropClick Observable, w przeciwnym razie wprowadzisz wyciek pamięci.
ponury
3

A co powiesz na zabawę z tymi dwoma właściwościami?

disableClose: boolean - określa, czy użytkownik może użyć klawisza Escape lub kliknąć tło, aby zamknąć modal.

hasBackdrop: boolean - określa, czy okno dialogowe ma tło.

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

alansiqueira27
źródło
ustawienie hasBackdrop na false usuwa zaczernienie obszaru poza oknem
Mohit Atray
Praca z Angular 9. „hasBackdrop” nie pozwala użytkownikowi na interakcję z innymi elementami zewnętrznymi. disableClose nie pozwala użytkownikowi na zamknięcie okna za pomocą zewnętrznego kliknięcia lub klawisza Escape.
Naveen Kumar V
0

Dodaj

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

do kodu modelu.

Sachini Witharana
źródło