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

Angular借助跨组件Service传递选中ID实现详情页上下页切换的问题

问题核心痛点分析

  • 原有实现预生成全量分页参数数组的逻辑冗余,且root级Service的全局状态没有在每次用户重新选择记录时完全重置,导致旧数据残留
  • 跳转逻辑和索引维护强耦合,手动维护索引容易出现计算偏差,和路由参数不同步

优化实现方案

1. 重构Service代码

interface PaginationState {
  nextDisabled: boolean;
  prevDisabled: boolean;
}

@Injectable({
  providedIn: 'root'
})
export class EventsService implements Resolve<Events> {
  constructor(
    private dataService: BaseDataService, 
    private router: Router
  ) { }

  // 用BehaviorSubject存选中ID数组,默认空数组
  private selectedIds$ = new BehaviorSubject<number[]>([]);
  // 存当前查看的索引,默认0
  private currentIndex$ = new BehaviorSubject<number>(0);

  // 外部只读访问当前选中ID数组
  get selectedIds() {
    return this.selectedIds$.value;
  }

  // 分页状态动态计算,无需预生成全量参数
  get paginationState(): PaginationState {
    const ids = this.selectedIds$.value;
    const currentIdx = this.currentIndex$.value;
    return {
      nextDisabled: currentIdx >= ids.length - 1,
      prevDisabled: currentIdx <= 0
    };
  }

  // 表格页调用,传入新选中的ID数组
  setSelectedIds(ids: number[]): void {
    if (!Array.isArray(ids) || ids.length === 0) return;
    this.selectedIds$.next([...ids]); // 新数组直接覆盖旧值,无残留
    this.currentIndex$.next(0); // 每次传入新ID自动重置索引到第一条
  }

  // 详情页路由变化时调用,同步当前索引
  setCurrentIndexById(id: number): void {
    const idx = this.selectedIds$.value.findIndex(item => item === id);
    if (idx > -1) {
      this.currentIndex$.next(idx);
    }
  }

  // 获取下一页ID,返回null表示不可跳转
  getNextId(): number | null {
    if (this.paginationState.nextDisabled) return null;
    const nextIdx = this.currentIndex$.value + 1;
    this.currentIndex$.next(nextIdx);
    return this.selectedIds$.value[nextIdx];
  }

  // 获取上一页ID,返回null表示不可跳转
  getPrevId(): number | null {
    if (this.paginationState.prevDisabled) return null;
    const prevIdx = this.currentIndex$.value - 1;
    this.currentIndex$.next(prevIdx);
    return this.selectedIds$.value[prevIdx];
  }

  // 原有resolve逻辑保留即可
  resolve(route: ActivatedRouteSnapshot) {
    const id = route.params['id'];
    return this.dataService.get(`/api/events/${id}`);
  }
}

2. 调整表格页代码

只需传入选中ID数组即可,无需额外调用初始化方法:

onDetails() {
  // 直接映射得到ID数组,避免旧选中项残留
  this.selectedIds = this.selectedKeys.map(x => x.id);
  this.eventDetailsService.setSelectedIds(this.selectedIds);
  this.router.navigate(["details/", this.selectedIds[0]], { relativeTo: this.route });
}

3. 调整详情页代码

ngOnInit() {
  // 监听路由ID参数,自动同步Service当前索引
  this.route.params.pipe(takeUntil(this.destroyed$)).subscribe(params => {
    const currentId = Number(params['id']);
    this.eventDetailsService.setCurrentIndexById(currentId);
    // 同步按钮禁用状态
    this.nextDisabled = this.eventDetailsService.paginationState.nextDisabled;
    this.prevDisabled = this.eventDetailsService.paginationState.prevDisabled;
  });

  this.route.data.pipe(takeUntil(this.destroyed$)).subscribe((result) => {
    this.entity = result.Events.value[0] as Events;
  });

  this.editRestorationDataSource.data = editRestorationData;
  this.editRepairDataSource.data = editRepairData;
}

nextPage() {
  const nextId = this.eventDetailsService.getNextId();
  if (nextId) {
    this.router.navigate([`/details/${nextId}`]);
  }
}

previousPage() {
  const prevId = this.eventDetailsService.getPrevId();
  if (prevId) {
    this.router.navigate([`/details/${prevId}`]);
  }
}

onCancel(): void {
  this.navigateBackToGrid();
}

方案优势

  • 完全解决旧数据残留问题:每次用户重新选择记录时,新的ID数组直接覆盖旧值,所有状态自动重置
  • 去掉冗余的预生成分页参数逻辑,所有分页状态和跳转ID都是基于当前数据动态计算,不会出现无效引用
  • 索引和路由参数自动同步,即使用户手动刷新详情页,只要Service的ID数组还在,就能正确匹配当前索引和按钮状态
  • 后续如果需要支持响应式更新,只需把paginationState也封装成可观察对象,详情页直接订阅就能自动更新按钮禁用状态,无需手动赋值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 06:06:03