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?
We can pass ActivatedRoute to service from component. Then subscribe to route.params in service class
Acording to this you have to traverse down the route tree and get the data from the route at the bottom of the tree.
@Injectable()
export class MyService{
constructor(private router:Router,private route:ActivatedRoute){
this.router.events
.filter(event => event instanceof NavigationEnd)
.subscribe((event) => {
let r=this.route;
while (r.firstChild) {
r = r.firstChild
}
//we need to use first, or we will end up having
//an increasing number of subscriptions after each route change.
r.params.first().subscribe(params=>{
// Now you can use the params to do whatever you want
});
});
}
}
the problem is the
return this.route.params;
the route params are not ready at that moment -> observables -> asynchronicity
I like managing state through the URL, and built a simple state service that observes route navigation end events and exposes observable endpoints for each route parameter.
import { Injectable } from '@angular/core';
import {NavigationEnd, Router} from '@angular/router';
import {BehaviorSubject} from 'rxjs';
import { filter } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class DigStateService {
public state = {};
constructor(private router: Router) {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd)
).subscribe(() => {
let route = this.router.routerState.snapshot.root;
do {
const params = route.params;
const keys = Object.keys(params);
if (keys.length > 0) {
keys.forEach(key => {
const val = params[key];
if (this.state[key]) {
this.state[key].next(val);
} else {
this.state[key] = new BehaviorSubject(val);
}
});
}
route = route.firstChild;
} while (route);
});
}
param(key) {
// if this key does not exist yet create it so its observable when it is set
if (! this.state[key]) {
this.state[key] = new BehaviorSubject(null);
}
return this.state[key];
}
}
Then you can use this service to observe individual route params from anywhere in the tree:
stateService.param('project').subscribe(projectId => {
console.log('project ' + projectId);
});
来源:https://stackoverflow.com/questions/40219790/angular-2-get-routeparams-in-a-service