自定义 ErrorHandler 提供程序为响应异步事件而打开的对话框不会关闭

Dialog opened by custom ErrorHandler provider in response to async event does not close

我有一个通用的警报对话框组件,我在整个 Angular 应用程序(简化)中用于各种目的...

@Component({
  selector: 'app-alert-dialog',
  template: `<mat-dialog-content>{{message}}</mat-dialog-content>
<mat-dialog-actions align="end">
  <button mat-raised-button mat-dialog-close>{{buttonText}}</button>
</mat-dialog-actions>`
})
export class AlertDialog {
  message: string = 'An unspecified error has occurred';
  buttonText = 'Cancel';

  constructor(
    @Inject(MAT_DIALOG_DATA)
    private data: {
      message: string;
      buttonText: string;
    },
    private dialogRef: MatDialogRef<AlertDialog>
  ) {
    if (data?.message) this.message = data.message;
    if (data?.buttonText) this.buttonText = data.buttonText;
  }
}

对话框 windows 指定 app.module 提供商中的默认选项:

@NgModule({
  ...
  providers: [
    { provide: ErrorHandler, useClass: ErrorHandlerService },
    // default options for dialogs
    {
      provide: MAT_DIALOG_DEFAULT_OPTIONS,
      useValue: {
        disableClose: true,
        hasBackdrop: true
      }
    }
  ]
})

我还实现了一个自定义 ErrorHandler 提供程序,它通过警报对话框显示相关错误。

@Injectable({
  providedIn: 'root'
})
export class ErrorHandlerService extends ErrorHandler {
  constructor(private dialog: MatDialog) {
    super();
  }

  handleError(err: any): void {
    console.error(err);

    this.dialog.open(AlertDialog, {
      data: { message: err.message }
    });
  }
}

显示的错误多为后台服务器异步返回的错误

在异步抛出错误的情况下,对话框不会关闭以响应按钮(即使使用 (click)="closeDialog()" 处理程序),除非您单击该按钮然后还单击该按钮的其他位置。

我有一个 StackBlitz 项目演示了这里的问题: https://stackblitz.com/edit/angular-ivy-b3fqjj

有没有办法通过单击按钮关闭异步打开的对话框?

使用 ngZone。改进代码:

  constructor(private dialog: MatDialog, private ngZone: NgZone) {
    super();
  }

  handleError(err: any): void {
    console.error(err);
    this.ngZone.run(() => {
      this.dialog.open(AlertDialog, {
        data: { icon: 'Error', message: err.message, buttonText: 'Uh oh!' }
      });
    });
  }

有关详细信息,请参阅 answer