Как закрыть диалог мата без фона при нажатии снаружи?

Как я могу закрыть диалоговое окно в этом примере stackblitz (минимальный, воспроизводимый пример), щелкнув снаружи?

Это нормально работает, если я удалю свойство hasBackdrop: false-> Пример рабочего Stackblitz

3 ответа

Решение

Короче говоря, вам нужно самостоятельно обрабатывать клики - слушать клики и определять, находятся ли они за пределами диалога. Это позволяет не улавливать событие щелчка так, как это делает фон. Вот пример StackBlitz, основанный на вашем:

@Component({
  selector: 'dialog-overview-example',
  templateUrl: 'dialog-overview-example.html',
  styleUrls: ['dialog-overview-example.css'],
})
export class DialogOverviewExample {

  @HostListener('document:click', ['$event'])
  clickout(event) {
    if (this.clickoutHandler) {
      this.clickoutHandler(event);
    }
  }

  animal: string;
  name: string;

  clickoutHandler: Function;

  dialogRef: MatDialogRef<DialogOverviewExampleDialog>;

  constructor(public dialog: MatDialog) {}

  openDialog(): void {
    setTimeout(() => {
      this.dialogRef = this.dialog.open(DialogOverviewExampleDialog, {
        width: '250px',
        hasBackdrop: false
      });

      this.dialogRef.afterOpened().subscribe(() => {
        this.clickoutHandler = this.closeDialogFromClickout;
      });

      this.dialogRef.afterClosed().subscribe(() => {
        this.clickoutHandler = null;
      });
    });
  }

  closeDialogFromClickout(event: MouseEvent) {
    const matDialogContainerEl = this.dialogRef.componentInstance.hostElement.nativeElement.parentElement;
    const rect = matDialogContainerEl.getBoundingClientRect()
    if(event.clientX <= rect.left || event.clientX >= rect.right || 
        event.clientY <= rect.top || event.clientY >= rect.bottom) {
      this.dialogRef.close();
    }
  }
}

@Component({
  selector: 'dialog-overview-example-dialog',
  templateUrl: 'dialog-overview-example-dialog.html',
})
export class DialogOverviewExampleDialog {

  constructor(
    public hostElement: ElementRef,
    public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
    @Inject(MAT_DIALOG_DATA) public data: DialogData) {
  }

  onNoClick(): void {
    this.dialogRef.close();
  }
}

Стандартный подход к созданию диалогового окна Angular Material, которое закрывается при щелчке за пределами диалогового окна (при создании внешнего вида без фона), заключается в использовании встроенной библиотеки класса CSS.cdk-overlay-transparent-backdrop и примените его с помощью MatDialogConfig свойство backdropClass.

В openDialog метод будет:

openDialog(): void {
  const dialogRef = this.dialog.open(DialogOverviewExampleDialog, {
    backdropClass: 'cdk-overlay-transparent-backdrop',
    hasBackdrop: true,
    width: '250px'
  });
}

См. Пример Stackblitz

Есть много способов добиться этого. Можно было бы слушать щелчки окон. Stackblitz

export class DialogOverviewExampleDialog {

  private inited;

  constructor(
    public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
    @Inject(MAT_DIALOG_DATA) public data: DialogData) { }

  ngOnInit() {
      this.dialogRef.afterOpened().subscribe(() => {
        this.inited = true;
      })
  }

  @HostListener('window:click')
  onNoClick(): void {
    if (this.inited) {
        this.dialogRef.close();
    }
  }

}

Но я предлагаю вам отредактировать CSS для фона, чтобы он оставался невидимым, но функциональность оставалась.

.cdk-overlay-dark-backdrop {
    background: transparent;
}
Другие вопросы по тегам