Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 get routeParams in a service

I want to shift the logic from component to service. But I found out that I can't get the routeParams in a service.

My component looks like

import { Component, OnInit }      from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';

import { MyService }              from '../services/my.service';

@Component({
  moduleId: module.id,
  templateUrl: 'my.component.html',
  styleUrls: ['my.component.css']
})
export class MyComponent implements OnInit {
  constructor(private myService: MyService, private route: ActivatedRoute) {;}

  public ngOnInit() {
    this.route.params
      .subscribe((params: Params) => {
        debugger;
        console.log(params);
      });
    this.myService.getParams()
      .subscribe((params: Params) => {
        debugger;
        console.log('Return1:');
        console.log(params);
      }, (params: Params) => {
        debugger;
        console.log('Return2:');
        console.log(params);
      }, () => {
        debugger;
        console.log('Return3:');
    });
  }
};

My service looks like

import { Injectable }                     from '@angular/core';
import { Params, ActivatedRoute }         from '@angular/router';

import { Observable }                     from 'rxjs';

@Injectable()
export class MyService {
  constructor(private route: ActivatedRoute) {;}

  public getParams(): Observable<Params> {       
    this.route.params.subscribe((params: Params) => {
      debugger;
      console.log('Service1:');
      console.log(params);
    }, (params: Params) => {
      debugger;
      console.log('Service2:');
      console.log(params);
    }, () => {
      debugger;
      console.log('Service3:');
    });
    return this.route.params;
  }
};

When I debug I can see that params are filled in component and empty in service. That's the result

Component:
Object {param: "1"}
Service1:
Object {}
Return1:
Object {}

I'm using Angular 2.0.0. Why the difference in component and service? Is it possible to get params in a service?

EDIT: https://github.com/angular/angular/issues/11023

like image 444
Thomas Sablik Avatar asked Oct 24 '16 13:10

Thomas Sablik


People also ask

How do you find Route parameters?

The first way is through the route snapshot. The route snapshot provides the initial value of the route parameter map (called the paramMap ). You can access the parameters directly without subscribing or adding observable operators. The paramMap provides methods to handle parameter access like get , getAll , and has .

Can activate guard in Angular?

The canActivate guard checks if the user can visit the specific route or we have to prevent access to that specific route. We use the this guard when we have to check some condition and based on that users have the access to reach that specific route or not, before activating the component or showing it to the user.


1 Answers

Credit to @juansb827 this is an updated continuation of his answer (which uses old RxJS syntax). Simply create a service as follows:

import { Injectable } from '@angular/core';
import { filter, first } from 'rxjs/operators';
import { ActivatedRoute, NavigationEnd, Params, Router, RouterEvent } from '@angular/router';
import { ReplaySubject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class RouteParamsService {
  private routeParamsChangeSource = new ReplaySubject<Params>();
  routeParamsChange$ = this.routeParamsChangeSource.asObservable();

  constructor(private router: Router, private route: ActivatedRoute) {
    this.router.events
      .pipe(filter((event: RouterEvent) => event instanceof NavigationEnd))
      .subscribe(() => {
        let r = this.route;
        while (r.firstChild) r = r.firstChild;
        r.params.pipe(first()).subscribe((params: Params) => {
          this.routeParamsChangeSource.next(params);
        });
      });
  }
}

You can now hook into this service from anywhere in your app (including other services, components, interceptors, etc) as follows:

constructor(private routeParamsService: RouteParamsService) {
  this.routeParamsService.routeParamsChange$.subscribe((params: Params) => {
    console.log('params', params);
  });
}

And this will fire whenever the URL changes and emit the current params. Within a component you would place this code in ngOnInit instead of the constructor.

You may want to use a Subject instead of a ReplaySubject depending on your needs. A ReplaySubject will fire as soon as you subscribe with the last value emitted. A Subject will only fire on new emits after subscribing.

like image 167
danday74 Avatar answered Oct 12 '22 20:10

danday74