typescript 无论使用 ActivatedRoute 的路由嵌套级别如何,都可以检索 Angular2 路由上的数据属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38877123/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Retrieving a data property on an Angular2 route regardless of the level of route nesting using ActivatedRoute
提问by balteo
I have defined a number of routes as follows:
我已经定义了一些路由如下:
export const AppRoutes: Routes = [
{path: '', component: HomeComponent, data: {titleKey: 'homeTitle'}},
{path: 'signup', component: SignupComponent, data: {titleKey: 'SIGNUP_FORM.TITLE'}},
{path: 'signin', component: SigninComponent, data: {titleKey: 'SIGNIN_FORM.TITLE'}},
{path: 'sendpasswordresetinformation', component: SendPasswordResetInformationComponent},
{path: 'password/reset/:userAccountToken', component: PasswordResetComponent},
{
path: 'dashboard', component: DashboardComponent, children: [
{path: '', component: DashboardSummaryComponent},
{
path: 'message', children: [
{path: '', component: MessageSummaryComponent, data: {titleKey: 'MESSAGE_LIST.TITLE'}},
{path: 'conversation/:otherId', component: MessageConversationComponent, data: {titleKey: 'XXX'}}]
},
{
path: 'useraccount', component: UserAccountComponent, children: [
{
path: '',
component: UserAccountSummaryComponent,
data: {titleKey: 'XXX'},
resolve: {
userAccount: UserAccountResolve
}
},
{path: 'address', component: UserAccountAddressComponent, data: {titleKey: 'ADDRESS_FORM.TITLE'}},
{path: 'email', component: UserAccountEmailComponent, data: {titleKey: 'EMAIL_FORM.TITLE'}},
{
path: 'emailnotification',
component: UserAccountEmailNotificationComponent,
data: {titleKey: 'EMAIL_NOTIFICATION_FORM.TITLE'}
},
{path: 'firstname', component: UserAccountFirstNameComponent, data: {titleKey: 'FIRST_NAME_FORM.TITLE'}},
{path: 'password', component: UserAccountPasswordComponent, data: {titleKey: 'PASSWORD_FORM.TITLE'}}]
}]
}];
Some of the routes are children of others.
一些路线是其他路线的孩子。
I would like to find a way to retrieve the titleKey
property on data
regardless of whether the route is a top level route or the child of another.
我想找到一种方法来检索titleKey
属性,data
无论该路线是顶级路线还是另一个路线的子路线。
Here is what I have tried:
这是我尝试过的:
export class AppComponent implements OnInit {
constructor(private translate: TranslateService,
private sessionService: SessionService,
private titleService: Title,
private activatedRoute: ActivatedRoute) {
let userLang = 'fr';
translate.use(userLang);
moment.locale(userLang);
}
ngOnInit() {
this.sessionService.reloadPersonalInfo();
}
setTitle($event) {
this.translate.get(this.activatedRoute.snapshot.data['titleKey'])
.subscribe(translation=>this.titleService.setTitle(translation));
}
}
this.activatedRoute.snapshot.data['titleKey']
is undefined
.
this.activatedRoute.snapshot.data['titleKey']
是undefined
。
Can someone please advise how to retrieve a property on route data
regardless of the level of nesting of the route?
有人可以建议如何在路线上检索属性,data
而不管路线的嵌套级别如何?
edit: After reading the official angular documentation about ActivatedRoute, I tried to use the map
operator on the data property of the ActivatedRoute
instance as follows:
编辑:阅读有关 ActivatedRoute的官方角度文档后,我尝试map
在ActivatedRoute
实例的 data 属性上使用运算符,如下所示:
@Component({
selector: 'app',
template: `
<section class="container-fluid row Conteneur">
<appNavbar></appNavbar>
<section class="container">
<router-outlet (activate)="setTitle($event)"></router-outlet>
</section>
</section>
<section class="container-fluid">
<appFooter></appFooter>
</section>
`,
directives: [NavbarComponent, FooterComponent, SigninComponent, HomeComponent, ROUTER_DIRECTIVES]
})
export class AppComponent implements OnInit {
constructor(private translate: TranslateService,
private sessionService: SessionService,
private titleService: Title,
private activatedRoute: ActivatedRoute) {
let userLang = 'fr';
translate.use(userLang);
moment.locale(userLang);
}
ngOnInit() {
this.sessionService.reloadPersonalInfo();
}
setTitle($event) {
this.activatedRoute.data.map(data=>data['titleKey'])
.do(key=>console.log(key))
.switchMap(key=>this.translate.get(key))
.subscribe(translation=>this.titleService.setTitle(translation));
}
}
and yet key
is always undefined...
但key
始终未定义......
采纳答案by balteo
I stumbled on a nice tutorial with a clean solution: https://toddmotto.com/dynamic-page-titles-angular-2-router-events.
我偶然发现了一个很好的教程,里面有一个干净的解决方案:https: //toddmotto.com/dynamic-page-titles-angular-2-router-events。
Here is what I finally came up with using the solution from the above tutorial and using the ng2 translate servicein order to convert the titleKeys
specified in my route data into proper labels:
这是我最终使用上述教程中的解决方案并使用ng2 翻译服务将titleKeys
我的路线数据中指定的转换为正确标签的方法:
@Component({
selector: 'app',
encapsulation: ViewEncapsulation.None,
styleUrls: ['../styles/bootstrap.scss'],
template: `<section class="container-fluid row Conteneur">
<app-navbar></app-navbar>
<section class="container">
<router-outlet></router-outlet>
</section>
</section>
<section class="container-fluid">
<app-footer></app-footer>
</section>`
})
export class AppComponent implements OnInit {
constructor(private translate: TranslateService,
private sessionSigninService: SessionSigninService,
private titleService: Title,
private router: Router,
private activatedRoute: ActivatedRoute) {
let userLang = 'fr';
translate.use(userLang);
moment.locale(userLang);
}
ngOnInit() {
this.router.events
.filter(event => event instanceof NavigationEnd)
.map(() => this.activatedRoute)
.map(route => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter(route => route.outlet === 'primary')
.mergeMap(route => route.data)
.mergeMap(data => this.translate.get(data['titleKey']))
.subscribe(translation => this.titleService.setTitle(translation));
}
}
回答by Robba
We had this same problem. We decided to go about it another way. Instead of trying to listen for the data emits on the ActivatedRoute, we subscribe to the events
Observable on the router itself:
我们遇到了同样的问题。我们决定换一种方式去做。我们没有尝试侦听 ActivatedRoute 上发出的数据,而是订阅events
路由器本身上的 Observable:
import { Component } from "@angular/core";
import { NavigationEnd, Router } from "@angular/router";
declare var module: any;
@Component({
moduleId: module.id,
selector: "app-layout",
templateUrl: "main-layout.component.html"
})
export class LayoutComponent {
titleKey: string;
constructor(private router: Router){}
ngOnInit() {
this.router.events
.filter((event: any) => event instanceof NavigationEnd)
.subscribe(() => {
var root = this.router.routerState.snapshot.root;
while (root) {
if (root.children && root.children.length) {
root = root.children[0];
} else if (root.data && root.data["titleKey"]) {
this.titleKey = root.data["titleKey"];
return;
} else {
return;
}
}
});
}
}
Note that we're using the value in a component that is used at the top level but needs the data from the deepest child route. You should be able to pretty easily convert this to a service that emits events whenever the titleKey
changes value.
请注意,我们在顶层使用的组件中使用该值,但需要来自最深子路由的数据。您应该能够非常轻松地将其转换为每当titleKey
更改值时发出事件的服务。
Hope this helps.
希望这可以帮助。
回答by Madhu Ranjan
Update
更新
You may try below in AppComponent
,
你可以在下面尝试AppComponent
,
constructor(private translate: TranslateService,
private sessionService: SessionService,
private titleService: Title,
private activatedRoute: ActivatedRoute) {
this.router.events.subscribe((arg) => {
if(arg instanceof NavigationEnd) {
console.log(this.getTitle(this.activatedRoute.snapshot));
}
});
}
getTitle = (snapshot) => {
if(!!snapshot && !!snapshot.children && !!snapshot.children.length > 0){
return this.getTitle(snapshot.children[0]);
}
else if(!!snapshot.data && !!snapshot.data['titleKey']){
return snapshot.data['titleKey'];
}
else{
return '';
}
}
seems little hacky but works.
似乎有点hacky但有效。
Old
老的
You may try below,
你可以试试下面,
{
path: 'conversation/:otherId',
component: MessageConversationComponent,
data: {titleKey: 'XXX'},
// add below resolve
resolve: {
titleKey: MessageConversationResolve
}
}
add a new service MessageConversationResolve.tsand add it appropriately in providers.
添加一个新服务MessageConversationResolve.ts并在提供者中适当地添加它。
import { Injectable } from '@angular/core';
import { Router, Resolve,ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AdminDetailResolve implements Resolve<any> {
constructor(private router: Router,
private titleService: Title) {}
resolve(route: ActivatedRouteSnapshot): Observable<any> | Promise<any> | any {
// route.data will give you the titleKey property
// console.log(route.data);
// you may consume titleService here to setTitle
return route.data.titleKey;
}
}
Below is angular version which supports above solution,
以下是支持上述解决方案的角度版本,
Angular 2 version : 2.0.0-rc.5
Angular 2 version : 2.0.0-rc.5
Angular Router version : 3.0.0-rc.1
Angular Router version : 3.0.0-rc.1
Hope this helps!!
希望这可以帮助!!