Angular嵌套路由paramMap预订

时间:2017-08-24 16:09:22

标签: angular rxjs

我认为这是一个更rxjs相关的问题,但我在Angular App中面对它。

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

我将尝试逐步解释代码的工作原理。

我们有一个带有合同列表的DropDown。 我们有一个带有年份列表的DropDown。

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

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

用户还可以更改DropDown年份中的年份。

一旦用户更改DropDown年份中的选择,我们还必须导航并更新所选年份的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但是当选择发生变化时,带有年份的DropDown将不再触发订阅。

解决此类嵌套调用的最佳方法是什么?

修改

我修好了 - 不是那么优雅的IMO:

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来说明这个场景:

https://plnkr.co/edit/Z3AqcayxSALiWGoI7KRE?p=preview

2 个答案:

答案 0 :(得分:1)

解决方案是使用switchMap而不是几个subscribers,我们在这里:

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(() => {});

答案 1 :(得分:0)

好的,我花了一些时间与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:https://plnkr.co/edit/7Pn6HX3D6fZ8iHdylbUW?p=preview