What is the best way to get current route params in Angular 6 services?

19,654

Solution 1

Since you want the current route params, instead of activatedRoute.snapshot, you should be subscribing to activatedRoute.params. It will give you the latest and updated value of the current route params.

Your service method should not be responsible for getting the id from the ActivatedRoute. It should be the responsibility of your Component. Your service should only be responsible for getting the id from the component and then do the needful based on that id.

You should be extracting the id from the activatedRoute in your component. And then call the service method by passing it the id

export class MainComponent {
    constructor(
        private dataService: DataService, 
        private activeRoute: ActivatedRoute
    ) { }

    getChartsData() {
        this.activeRoute.params.subscribe(params => {
            if(params['id']) {
                this.dataService.getChartsData(params['id'])
                    .subscribe(data => console.log(data));
            }
        })

    }
}

And in your service

@Injectable({
  providedIn: "root"
})
export class DataService {
    getChartsData(id) {
        if (id) {
            ...
        } else {
            ...
        }
    }
}

Solution 2

In most cases services should not access routing. A "ChartDataService" should load and return charts that are identified by something (e.g. an id). Remember: If you access the current route directly in the service, you must never change the parameter name because this would break your data service.

export class ChartDataService {
  getChart(id: string) { … }
}

// in your component
const chartId = // read from activated route
this.chartsService.getChart(chartId);

If you really want to to access the current route in a service, you cannot inject ActivatedRoute (this is by design see e.g. https://github.com/angular/angular/issues/12884). But you can inject the Router itself and listen for navigation events:

class MyClass {
  constructor(private router: Router) {
    router.events.subscribe((val) => {
        // see also 
        console.log(val instanceof NavigationEnd) 
    });
  }
}

Example from https://stackoverflow.com/a/33548895/2085502.

Docs: https://angular.io/guide/router#router-events

Share:
19,654

Related videos on Youtube

SMH
Author by

SMH

Updated on June 04, 2022

Comments

  • SMH
    SMH almost 2 years

    I am trying to find out what is the best way to get the current route params in Angular 6.

    At the moment I have to pass the ActivatedRoute to the service's method as argument and then use it in the service.

    export class MainComponent {
        constructor(private dataService: DataService, private activeRoute: ActivatedRoute) { }
    
        getChartsData() {
            return this.dataService(this.activeRoute);
        }
    }
    
    @Injectable({
      providedIn: "root"
    })
    export class DataService {
        getChartsData(activatedRoute) {
            if (activatedRoute.snapshot.params['id']) {
                ...
            } else {
                ...
            }
        }
    }
    
    • Roberto Zvjerković
      Roberto Zvjerković over 5 years
      Can't you just inject ActivatedRoute in the service?
    • SMH
      SMH over 5 years
      @ritaj I was doing that but I was getting empty object when I try to get the current route params.
    • Stavm
      Stavm over 5 years
      using snapshot.params is only good for when the component first loads. what you're after is subscribing to the observable. this.activatedRoute.params. so it will be something like: this.activatedRoute.params.subscribe((params: Params) => console.log(params['id']))