我想将逻辑从组件转移到服务。但我发现我无法在服务中获得routeParams。
我的组件看起来像
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:');
});
}
};
我的服务看起来像
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;
}
};
当我调试时,我可以看到params填充组件并且在服务中为空。这就是结果
Component:
Object {param: "1"}
Service1:
Object {}
Return1:
Object {}
我正在使用Angular 2.0.0。为什么组件和服务有所不同?是否有可能在服务中获得参数?
答案 0 :(得分:7)
根据this,您必须遍历路径树,并从树底部的路径获取数据。
@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
});
});
}
}
答案 1 :(得分:2)
我们可以将ActivatedRoute传递给组件服务。然后订阅服务类
中的route.params答案 2 :(得分:2)
类似的事情在Angular 8中对我有效:
export class TheService {
params$: Observable<any>;
constructor(private router: Router) {
this.params$ = this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
map(event => this.getLeafRoute(this.router.routerState.root).snapshot.params)
);
}
private getLeafRoute(route: ActivatedRoute): ActivatedRoute {
if (route === null) return null; //or throw ?
while (route.firstChild) route = route.firstChild;
return route;
}
}
答案 3 :(得分:2)
这应该可以帮助任何想要通过所有子路由递归获取参数的人:
import { Injectable } from '@angular/core';
import { Params, Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { filter, map, startWith } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class RouterParamsService {
private routeParamsChangeSource = new BehaviorSubject<Params>({});
change$ = this.routeParamsChangeSource.asObservable();
constructor(private router: Router, private activatedRoute: ActivatedRoute) {
const route$ = this.router.events.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.activatedRoute)
);
const primaryRoute$ = route$.pipe(
startWith(this.activatedRoute),
map((route) => {
let params = {};
while (route.firstChild) {
params = {
...params,
...route.snapshot.params
};
route = route.firstChild;
}
params = {
...params,
...route.snapshot.params
};
return { route, params };
}),
filter((data) => data.route.outlet === 'primary')
);
primaryRoute$.subscribe((data) => {
this.routeParamsChangeSource.next(data.params);
});
}
}
答案 4 :(得分:0)
问题是
return this.route.params;
此时路线参数尚未准备就绪 - &gt;可观察的 - &gt;异步
答案 5 :(得分:0)
我喜欢通过URL管理状态,并构建了一个简单的状态服务,该服务可观察路线导航结束事件并公开每个路线参数的可观察端点。
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];
}
}
然后,您可以使用此服务从树中的任何位置观察各个路线参数:
stateService.param('project').subscribe(projectId => {
console.log('project ' + projectId);
});
答案 6 :(得分:0)
我使用@ juansb827回答,当我摆脱了事件过滤器并直接遍历该ActiveRoute时,就可以使用它。它为我工作。就我而言,该事件可能在服务执行时就已经发生,因为我的遍历使用的是服务中的另一种方法。
答案 7 :(得分:0)
感谢@juansb827 这是他的回答的更新延续(使用旧的 RxJS 语法)。简单地创建一个服务如下:
constructor(private routeParamsService: RouteParamsService) {
this.routeParamsService.routeParamsChange$.subscribe((params: Params) => {
console.log('params', params);
});
}
您现在可以从应用程序的任何位置(包括其他服务、组件、拦截器等)连接到此服务,如下所示:
{{1}}
每当 URL 更改并发出当前参数时,它就会触发。 在组件中,您可以将此代码放在 ngOnInit 而不是构造函数中。
您可能希望根据需要使用主题而不是 ReplaySubject。一旦您订阅了最后一个发出的值,ReplaySubject 就会触发。 Subject 只会在订阅后触发新的发射。