首页 > 解决方案 > 自定义 ErrorHandler 提供程序为响应异步事件而打开的对话框未关闭

问题描述

我有一个通用的警报对话框组件,我在整个 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;
  }
}

对话框窗口在 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

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

标签: angularangular-materialangular-providersangular-errorhandlermaterial-dialog

解决方案


使用 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!' }
      });
    });
  }

有关详细信息,请参阅答案


推荐阅读