Angular 角度嵌套路由映射订阅

Angular 角度嵌套路由映射订阅,angular,rxjs,Angular,Rxjs,我认为这是一个与rxjs更相关的问题,但我在Angular应用程序中遇到了这个问题 我们在应用程序中嵌套了路由器事件订阅 我将尝试一步一步地解释代码是如何工作的 我们有一个合同列表的下拉列表。 我们有一个下拉列表,上面列出了年份 一旦用户更改合同下拉列表中的选择,我们需要导航并将合同id与所选合同id一起放入URL中,然后我们必须加载与此合同id相关的年份,我们订阅路由器事件: this.activatedRoute.parent.paramMap .map(m => +m.get("

我认为这是一个与rxjs更相关的问题,但我在Angular应用程序中遇到了这个问题

我们在应用程序中嵌套了路由器事件订阅

我将尝试一步一步地解释代码是如何工作的

我们有一个合同列表的下拉列表。 我们有一个下拉列表,上面列出了年份

一旦用户更改合同下拉列表中的选择,我们需要导航并将合同id与所选合同id一起放入URL中,然后我们必须加载与此合同id相关的年份,我们订阅路由器事件:

this.activatedRoute.parent.paramMap
  .map(m => +m.get("contractId"))
  .distinctUntilChanged()
  .subscribe(contractId => {
      // CALL SERVICE TO LOAD DROPDOWN WITH YEARS
  })
用户还可以在“年份”下拉列表中更改年份

一旦用户在“年份”下拉列表中更改选择,我们还必须导航并使用所选年份更新URL,然后我们需要用数据加载网格,这就是它的外观:

this.activatedRoute.parent.paramMap
  .map(m => +m.get("contractId"))
  .distinctUntilChanged()
  .subscribe(contractId => {
      // CALL SERVICE TO LOAD DROPDOWN WITH YEARS

      this.activatedRoute.queryParamMap
        .map(m => +m.get("year"))
        .distinctUntilChanged()
        .subscribe(year => {
        // CALL SERVICE TO LOAD GRID WITH DATA
      })
  });
这里的问题是,每次合同id更改时,我都会创建this.activatedRoute.queryParamMap的新订阅,这意味着几个重复的http请求

我也尝试过使用unsubscribe,但是当选择发生变化时,年份下拉菜单将不再触发订阅

解决这种嵌套调用的最佳方法是什么

编辑:

我把它修好了-我觉得没那么优雅:

let subscription = new Subscription();

this.activatedRoute.parent.paramMap
  .map(m => +m.get("contractId"))
  .distinctUntilChanged()
  .subscribe(contractId => {
      subscription.unsubscribe();

      // CALL SERVICE TO LOAD DROPDOWN WITH YEARS

      subscription = this.activatedRoute.queryParamMap
        .map(m => +m.get("year"))
        .distinctUntilChanged()
        .subscribe(year => {
        // CALL SERVICE TO LOAD GRID WITH DATA
      })
  });
也许rxjs提供了一种更优雅的解决方法

编辑:

我创建了一个plunker来演示这个场景:


好吧,我花了一段时间和普朗克在一起。我将ngOnInit更新如下:

  ngOnInit() {
    let contractId;
    let year;

    this.activatedRoute.parent.paramMap
        .subscribe(params => {
          this.contractId = params.get('contractId');
          console.log("Selected contract Id: " + this.contractId);
          // Code to populate the years from the contractid
        })

    this.activatedRoute.queryParamMap
      .subscribe(params => {
        this.year = params.get('year');
        console.log("Selected year: " + this.year)
        if (this.year) {
          this.loadGrid(this.contractId, this.year);
        } else {
          // Clear grid??
        }
      });
  }
第一次订阅会关注合同的变化,并获得新的一年

第二个订阅监视年份查询参数的更改并重新加载网格

我认为您不希望一个在另一个中,因为这会添加多个订阅

这就是你想要达到的目标吗

更新的plunker:

解决方案使用的是switchMap,而不是几个订阅者,我们来看看:

this.activatedRoute.parent.paramMap
.map(m => +m.get("contractId"))
.distinctUntilChanged()
.switchMap(contractId => {
  // CALL SERVICE TO LOAD DROPDOWN WITH YEARS

  return this.activatedRoute.queryParamMap
    .map(m => +m.get("year"))
    .distinctUntilChanged()
    .switchMap(year => {
    // CALL SERVICE TO LOAD GRID WITH DATA
  })
}).subscribe(() => {});

你有没有办法制作一个plunker来演示这一点?当然,我会这样做。Hello@DeborahK-我们来看看plunker:非常感谢@DeborahK。我忘了提到:当合同变更时,我需要再次加载年份下拉列表,因为每个合同都有不同的年份范围。很抱歉忘记了这一点,这就是为什么你的代码不起作用的原因。在我看来,它必须是嵌套的。问题是如何处理订阅。我可以通过每次合同变更都取消订阅来解决这个问题,但我觉得我太沉迷于rxjs了。我从你最初的帖子中了解到了这一点。因此,在我上面的代码中,使用文本代码填充从收缩开始的年份。我不明白为什么这会导致需要嵌套订阅?通过嵌套它们,您可以在用户每次更改父项时创建新订阅。然后你可能会有几十个或更多的订阅正在观看并试图执行。也许你可以更新我提供的plunker,并演示它在你的场景中是如何不起作用的?然后我可以看看如何编辑它。这只有在我们更改下拉列表的值时才起作用,但一旦应用程序启动ngOnInit(让我们假设路线中有年份),那么网格将被加载两次。我希望我能说清楚,我希望我没有把事情搞得太复杂。如何加载两次呢?你能带我去普朗克吗?你也在别的地方叫这个.loadGrid吗?