简体   繁体   English

角嵌套路由paramMap订阅

[英]Angular nested route paramMap subscriptions

I think this is a more rxjs related question, but I'm facing it in my Angular App. 我认为这是一个与rxjs相关的问题,但是我在Angular App rxjs面临着它。

we have in our application nested subscription of router event. 我们在应用程序中具有路由器事件的嵌套订阅。

I'll try to explain step-by-step how the code works. 我将逐步解释代码的工作原理。

We have a DropDown with a list of contracts. 我们有一个带有合同清单的下拉菜单。 And we have a DropDown with a list of years. 我们有一个带有年份列表的下拉列表。

Once the user change the selection in the contracts DropDown we need to navigate and put the contract id in the URL with the selected contract id, then we have to load the years related to this contract id, we subscribe to the router event: 一旦用户更改了合同DropDown中的选择,我们需要导航合同ID并将其放置在具有选定合同ID的URL中,然后我们必须加载与此合同ID相关的年份,我们订阅了router事件:

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

The user can also change the year in the years DropDown. 用户还可以更改DropDown年份中的年份。

Once the user change the selection in the years DropDown, we also have to navigate and update the URL with the selected year, then we need to load a grid with data, that is how it looks: 一旦用户在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
      })
  });

The problem here is that everytime the contract id changes, I create a new subscription of the this.activatedRoute.queryParamMap , that means, several duplicated http requests. 这里的问题是,每当合同ID更改时,我都会创建一个this.activatedRoute.queryParamMap的新订阅,这意味着几个重复的http请求。

I also tried using unsubscribe but the DropDown with the years won't trigger the subscription anymore when the selection changes. 我也尝试使用unsubscribe但是当选择更改时,具有年份的DropDown将不再触发订阅。

What is the best way to solve such a nested call? 解决此类嵌套调用的最佳方法是什么?

EDIT : 编辑

I fixed it - not so elegantly IMO: 我已将其修复-并非如此优雅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
      })
  });

Maybe rxjs offers a more elegant way of solving this? 也许rxjs提供了更优雅的解决方案?

EDIT: 编辑:

I created a plunker to ilustrate the scenario: 我创建了一个监听器来说明场景:

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

The solution was using switchMap instead of several subscribers , here we go: 解决方案是使用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(() => {});

OK, I spent some time with the Plunker. 好的,我在Plunker度过了一段时间。 I updated the ngOnInit as follows: 我将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??
        }
      });
  }

The first subscription watches for changes to the contract and gets new years. 第一个订阅会监视合同的更改并获得新的一年。

The second subscription watches for changes to the year query parameter and reloads the grid. 第二个订阅监视年份查询参数的更改并重新加载网格。

I don't think you want one within the other because that adds multiple subscriptions. 我不认为您想要一个在另一个内,因为这会增加多个订阅。

Is this what you were trying to achieve? 这是您要达到的目标吗?

Updated plunker: https://plnkr.co/edit/7Pn6HX3D6fZ8iHdylbUW?p=preview 更新的插件: https ://plnkr.co/edit/7Pn6HX3D6fZ8iHdylbUW ? p = preview

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM