user9150799
user9150799

Reputation:

Re-fetch data on route parameter change

Currently, I have:

  ngOnInit() {
    this.getPi();
  }

  getPi(): void {
    const term = this.route.snapshot.paramMap.get('category');
    console.log(term);
    this.piService.getPi(this.route.snapshot.paramMap.get('term')).subscribe(pi => {
      this.pi = pi;
    });
  }

This works fine when navigationg to localhost:4200/term1. However, when I navigate to another term (localhost:4200/term2 for example), ngOnInit doesn't get fired as no other component gets loaded.

How should I watch the changes so that I can call getPi()?

Upvotes: 3

Views: 3957

Answers (2)

Jota.Toledo
Jota.Toledo

Reputation: 28434

You have 2 approaches: Observable + async pipe or manually subscribe/unsubscribe

The first approach (best IMO):

import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/share';

export class FooComponent {
   pi$: Observable<any>;
   constructor(private piService: PiService){
      this.pi$ = this.route.paramMap.map(paramMap => paramMap.get('term')) /// map the route params to one element
     .switchMap(term => this.piService.getPi(term)) // change the main stream to the Http async request
     .share(); // prevent the request being done multiple times
   }
}

Furthermore, you need to use the async pipe in your template.

The second approach:

import {Subscription} from 'rxjs/Subscription';

export class FooComponent implements OnInit, OnDestroy {
   private termSub = Subscription.EMPTY;
   private term: any;
   ngOnInit(){
      this.termSub = this.route.paramMap.map(paramMap => paramMap.get('term')) /// map the route params to one element
      .subscribe(term => {
        this.term = term;
        this.getPi();
      });
   }

   getPi(){
     this.piService.getPi(this.term).subscribe(pi => this.pi = pi);
   }

   ngOnDestroy() {
     this.termSub.unsubscribe();
   }
}

Upvotes: 0

Iancovici
Iancovici

Reputation: 5731

You can reactively re-fetch by creating a subscription variable

termSubscriber: Subscription;

and may want to import

import {ActivatedRoute} from '@angular/router';
import {Subscription} from 'rxjs/Subscription';

and a term variable

term: string;

then subscribe to it

ngOnInit() { 
    this.termSubscriber= this.route.params
    .subscribe(
    (params: {Params}) => {
      this.term = params['term']);
    });
}

ngOnDestroy() { 
  this.termSubscriber.unsubscribe()
}

(will want to import OnDestroy like OnInit)

Note, if term1 is a route not a parmaeter, I'd convert it to

'/term/:id'

so you can make the id part fetchable.

Upvotes: 2

Related Questions