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

Angular页面刷新/URI直接访问时下拉框选中值丢失问题

问题:下拉框刷新/直接访问URI时丢失选中状态

存在两个问题:

  • 页面刷新后,下拉框的值变为空白
  • 通过URI直接访问链接时,下拉框为空

需求:根据当前所在的订单,保持下拉框的选中名称。场景为下拉框中有多个订单,选中某个订单后跳转到对应页面。


现有代码

Topbar组件

// Topbar:
export class AppTopbarComponent implements OnInit {
  items?: MenuItem[];
  orders: Order[] = [];
  filteredOrders: any[] = [];
  selectedOrder: any[] = [];
  displayRoutes: string[] = ['/order'];

  constructor(
    public appMain: AppMainComponent,
    private ordersService: OrderService,
    private router: Router,
    private orderSelectionService: OrderSelectionService
  ) {}

  ngOnInit(): void {
    this.ordersService.getAllOrders().subscribe((orders) => {
      this.orders = orders;
    });

    this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        const shouldDisplayDropdown = this.displayRoutes.some((route) => event.url.startsWith(route));
        this.selectedOrder = shouldDisplayDropdown ? this.selectedOrder : [];
      }
    });

    this.orderSelectionService.selectedOrderName$.subscribe((selectedOrderName) => {
      this.selectedOrder = selectedOrderName;
    });
  }

  onOrderSelect(event: any) {
    const selectedOrderId = event.Id;
    this.orderSelectionService.setSelectedOrderName(event || []);
    this.router.navigate(['/order', selectedOrderId, 'home']);
  }
}

订单选择Service

// Service:
@Injectable({
  providedIn: 'root',
})
export class OrderSelectionService {
  private selectedOrderSource = new BehaviorSubject<any[]>([]);

  selectedOrderName$: Observable<any[]> = this.selectedOrderSource.asObservable();

  setSelectedOrderName(orderName: any[]) {
    this.selectedOrderSource.next(orderName);
  }
}

尝试的方法(未成功)

尝试通过ActivatedRoute获取路由参数,但返回undefined:

this.activatedRoute.params.subscribe((params) => {
  console.log('Route Params:', params);
  const selectedOrderId = params['id'];
  this.selectedOrder = this.orders.find((order) => order.Id === selectedOrderId) || [];
});

解决方案

1. 核心问题分析

  • 路由参数是字符串类型,若order.Id是数字,会导致匹配失败
  • 订单数据加载异步,在orders未初始化时调用find会返回undefined
  • selectedOrder被定义为数组,但实际是单个订单对象,类型混乱
  • 导航结束时的逻辑未重新根据路由参数匹配订单

2. 修改后的代码

Topbar组件

export class AppTopbarComponent implements OnInit {
  items?: MenuItem[];
  orders: Order[] = [];
  filteredOrders: any[] = [];
  // 修正类型为单个订单对象或null
  selectedOrder: Order | null = null;
  displayRoutes: string[] = ['/order'];

  constructor(
    public appMain: AppMainComponent,
    private ordersService: OrderService,
    private router: Router,
    private orderSelectionService: OrderSelectionService,
    // 注入ActivatedRoute
    private activatedRoute: ActivatedRoute
  ) {}

  ngOnInit(): void {
    // 加载订单数据后,立即匹配当前路由的订单
    this.ordersService.getAllOrders().subscribe((orders) => {
      this.orders = orders;
      this.setSelectedOrderFromRoute();
    });

    // 监听导航结束事件,更新选中状态
    this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        const shouldDisplayDropdown = this.displayRoutes.some((route) => event.url.startsWith(route));
        if (shouldDisplayDropdown) {
          this.setSelectedOrderFromRoute();
        } else {
          this.selectedOrder = null;
          this.orderSelectionService.setSelectedOrder(null);
        }
      }
    });

    // 监听Service中的选中状态变化
    this.orderSelectionService.selectedOrder$.subscribe((selectedOrder) => {
      this.selectedOrder = selectedOrder;
    });
  }

  // 从路由参数中匹配并设置选中订单
  private setSelectedOrderFromRoute(): void {
    const selectedOrderId = this.activatedRoute.snapshot.paramMap.get('id');
    if (selectedOrderId && this.orders.length > 0) {
      // 转换参数类型,和order.Id匹配(如果Id是数字就用Number转换)
      const order = this.orders.find(o => o.Id.toString() === selectedOrderId);
      this.selectedOrder = order || null;
      this.orderSelectionService.setSelectedOrder(this.selectedOrder);
    }
  }

  onOrderSelect(event: Order) {
    this.selectedOrder = event;
    this.orderSelectionService.setSelectedOrder(event);
    this.router.navigate(['/order', event.Id, 'home']);
  }
}

订单选择Service

@Injectable({
  providedIn: 'root',
})
export class OrderSelectionService {
  // 修正类型为单个订单对象或null,初始值为null
  private selectedOrderSource = new BehaviorSubject<Order | null>(null);

  selectedOrder$: Observable<Order | null> = this.selectedOrderSource.asObservable();

  setSelectedOrder(order: Order | null) {
    this.selectedOrderSource.next(order);
  }
}

3. 关键优化点

  • 类型修正:将selectedOrder从数组改为单个Order对象或null,避免逻辑混乱
  • 参数类型匹配:将路由参数转换为和order.Id一致的类型(字符串或数字),确保匹配成功
  • 数据加载时机:在订单数据加载完成后再执行路由匹配,避免find返回undefined
  • 导航事件处理:每次导航结束后,重新根据路由参数设置选中状态,覆盖刷新/直接访问场景
  • 状态同步:确保组件和Service中的选中状态始终保持一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 04:27:12