问题
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
回答1:
We can pass ActivatedRoute to service from component. Then subscribe to route.params in service class
回答2:
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
});
});
}
}
回答3:
the problem is the
return this.route.params;
the route params are not ready at that moment -> observables -> asynchronicity
回答4:
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