使用 NGX 和状态管理打开模式

Opening modal using NGX and state management

我想使用 NGXS 打开模式,这将设置数据表的列可见性。

这是我的代码:

state.ts 文件:

@Action(OpenColumnModal)
openColumnModal(ctx: StateContext<FeedStateModel>) {
    const state = ctx.getState();
    const allCols = state.allColumns;
    return this.modalService.openColumnVisibilityModal(allCols).pipe(tap((result) => {
        ctx.setState({
            ...state,
            allColumns: result,
            userColumns: result.filter(col => col.visible)
        });
    })
}

modal.service.ts:

openColumnVisibilityModal(columns): Observable<any> {
    const dialogRef = this.dialog.open(ColumnVisibilityModal, {
        data: columns,
        autoFocus: false,
        hasBackdrop: true,
        disableClose: true
    });

    return dialogRef.afterClosed();
}

当我使用由 NGXS 打开的模式时,关闭状态事件后不会发出。之后,我需要点击某处调用openColumnModal函数内部的回调函数。

我正在使用 Angular Material 对话框。

有谁知道关闭modal后自动调用回调函数的方法吗?

提前致谢:)

尝试使用 subscribe 而不是 pipe:

@Action(OpenColumnModal)
openColumnModal(ctx: StateContext<FeedStateModel>) {
    const state = ctx.getState();
    const allCols = state.allColumns;
    return this.modalService.openColumnVisibilityModal(allCols).subscribe(result => {
        ctx.setState({
            ...state,
            allColumns: result,
            userColumns: result.filter(col => col.visible)
        });
    })
}

添加到 Armen 的 anser:管道用于链接不同的功能和 returns Observable。在管道中使用 Tap 来 运行 副作用(例如在管道之间记录值以进行调试等)。

查看 this RxJS docs page,您可以阅读:

Note: this is different to a subscribe on the Observable. If 
the Observable returned by tap is not subscribed, the side 
effects specified by the Observer will never happen. tap 
therefore simply spies on existing execution, it does not 
trigger an execution to happen like subscribe does.

换句话说:如果您不订阅您的管道返回的Observable,管道将不会运行 完全没有。您的修复:

return this.modalService.openColumnVisibilityModal(allCols).subscribe((result) => {
    ctx.setState({
        ...state,
        allColumns: result,
        userColumns: result.filter(col => col.visible)
    });
});

P.S。 - 建议在操作处理程序内部订阅的其他答案不正确,因为 NGXS 不是那样工作的!

您当前的方法是正确的,问题是操作处理程序 运行 在 Angular 的区域之外。只需将 NgZone class 注入您的状态并在 Angular 的区域内执行代码:

constructor(private modalService: ModalService, private zone: NgZone) {}

@Action(OpenColumnModal)
openColumnModal(ctx: StateContext<FeedStateModel>) {
  const state = ctx.getState();
  const allCols = state.allColumns;
  return this.zone.run(() =>
    this.modalService.openColumnVisibilityModal(allCols).pipe(
      tap(result => {
        ctx.setState({
          ...state,
          allColumns: result,
          userColumns: result.filter(col => col.visible)
        });
      })
    )
  );
}

当您发送任何操作时 - NGXS 使用 runOutsideAngular 在父区域内为该操作调用适当的处理程序,这是设计使然。

您还可以查看允许提供自己的 class 或使用现有 NoopNgxsExecutionStrategyexecutionStrategy option,不使用 NgZone class完全没有。