You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript使用Mat-Dialog实现两级级联删除弹窗的方案与失效排查

问题根因
  • 索引i失效问题:第一级弹窗确认后才触发第二级弹窗,两个弹窗的触发存在时间差,该时间段内如果dataSource.data数组发生了变化(比如其他行被新增/删除、表格切换分页、重新排序),你最初点击删除时拿到的索引i对应的行数据就会发生错位,甚至出现索引越界,导致传给删除接口的参数错误,请求直接失败。
  • 返回值校验逻辑异常:两级弹窗的afterClosed()回调返回值都命名为res,内层参数会屏蔽外层变量。同时如果你的第二级弹窗关闭时返回的不是布尔真值(比如用户点击取消返回false、填写的原因是空字符串,弹窗默认返回空值),内层的if(res)判断会直接不通过,删除逻辑自然不会执行。
  • 嵌套订阅的异步风险:RxJS中嵌套订阅属于不推荐的写法,没有统一的错误处理链路,只要其中某一步出现异常(比如弹窗组件报错、接口返回错误),整个逻辑会静默失败,很难排查问题。
两级删除弹窗最优实现方案

核心优化思路是用RxJS操作符打平异步流,避免嵌套订阅,提前锁定要删除的行数据,不依赖随时可能变化的索引,同时补充统一错误处理逻辑,参考实现代码如下:

import { filter, switchMap, catchError, EMPTY } from 'rxjs';

deleteRow(i: any) {
  // 提前锁定要删除的行数据,不依赖后续可能变化的索引i
  const targetDeleteRow = this.dataSource.data[i];
  this.dialogService
  .openConfigDialog('你确认要删除该文件吗?')
  .afterClosed()
  .pipe(
    // 第一级弹窗点确认才继续执行,否则直接中断流
    filter(firstConfirmRes => !!firstConfirmRes),
    // 打平第二级弹窗的异步流
    switchMap(() => this.reason.openReasonDialog("请填写删除原因").afterClosed()),
    // 第二级弹窗返回有效原因才继续执行
    filter(deleteReason => !!deleteReason),
    // 打平删除接口的异步流
    switchMap(() => {
      const deleteRowRequest = {
        IstValues: [targetDeleteRow]
      };
      return this.istManagementService.deleteRecord(this.inputTable, deleteRowRequest);
    }),
    // 统一捕获全链路的异常
    catchError(err => {
      console.error('删除失败,请重试', err);
      // 此处可补充错误提示弹窗逻辑
      return EMPTY;
    })
  )
  .subscribe(() => {
    // 删除成功后用对象匹配找索引,避免中间数据源变化导致删错行
    const finalDelIndex = this.dataSource.data.findIndex(item => item === targetDeleteRow);
    if (finalDelIndex > -1) {
      this.dataSource.data.splice(finalDelIndex, 1);
      this.dataSource._updateChangeSubscription();
    }
  })
}
                
refresh(): void { window.location.reload()}

内容的提问来源于stack exchange,提问作者leandroter7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 21:45:03