首页 > 解决方案 > 在 Angular Material 中处理对话框/模态的正确方法是什么?

问题描述

我正在使用AngularAngular Material构建应用程序。应用程序中的某些操作必须在模式/对话框中执行。出于这个原因,我使用MatDialog.

例如,假设我必须删除 auser并且这应该发生在对话框中。最简单的实现如下所示:

解决方案 1

deleteUser(user: User): void {
    const deleteUserDialogRef = this._dialog
        .open(DeleteUserDialogComponent, { data: { user } });

    deleteUserDialogRef
        .afterClosed()
        .subscribe((confirmed: boolean) => {
            if (confirmed) {
                this.usersService.delete(user.id);
            }
        });
}

解决方案 2

现在,假设您希望在对话框中有一个加载微调器,指示该操作仍处于挂起状态。为了使对话框保持简单,您必须牺牲实际打开它的父组件。

首先,您不必在用户单击“确认”按钮时实际关闭对话框,而是必须通过EventEmitter. 然后,您必须从父母那里收听该事件:

// ..
deleteUserDialogRef
    .componentInstance
    .confirmed
    .subscribe(() => this.usersService.delete(user.id))

为了改变loading对话框的输入,你必须这样做:

this.usersService
    .deleteUserLoading$
    .subscribe(loading => {
        deleteUserDialogRef
            .componentInstance
            .data
            .loading = loading;
    });

这并不难实现,但想象一下,如果您必须对所有 CRUD 操作执行相同的操作。您的对话框将很简单(并且具有演示性),但您的容器组件将变得巨大,并且可能难以阅读和管理。

解决方案 3

而不是遵循解决方案 2,您可以尝试使您的对话框更智能。您可以直接在模态中注入您的服务/存储并处理请求,在内部加载状态。然而,缺点是您必须通过服务/存储选择器注入您的用户数据,因为您不应该在智能组件中使用@Inputs()。

因此,您必须执行以下操作:

// Container
// ..
deleteUser(user: User): void {
    this.usersService.selectUser(user);

    const deleteUserDialogRef = this._dialog.open(DeleteUserDialogComponent);

    deleteUserDialogRef
        .afterClosed()
        .subscribe(() => this.usersService.deselectUser());
}

// Dialog
// ..
this.user$ = this.usersService.selectedUser$;

所以,我的问题是设计这个的正确方法是什么 -解决方案 2解决方案 3还是别的什么?

标签: angulardialogangular-materialngrx

解决方案


对我来说,解决方案是使用 NgRx Effects 来做到这一点。

因为它对组件隐藏了表单逻辑处理,并且可以从多个组件中使用同一个对话框。表单本身保持“哑”,逻辑进入效果。

@Effect()
openDialog = this.actions.pipe(
  ofType(LoginActionTypes.OpenLoginDialog),
  exhaustMap(_ => {
    let dialogRef = this.dialog.open(LoginDialog);
    return dialogRef.afterClosed();
  }),
  map((result: any) => {
    if (result === undefined) {
      return new CloseDialog();
    }
    return new LoginDialogSuccess(result);
  }),
);

更多信息请参阅开始使用 ngrx/effects


推荐阅读