[英]Angular - get component instance in router events
I'm trying to implement a title service for my angular 10 app.我正在尝试为我的 angular 10 应用程序实现标题服务。 I need to subscribe to router events, grab the activated route's component, see if it implements
title()
getter and then use it to set the page's title.我需要订阅路由事件,获取激活路由的组件,看看它是否实现了
title()
getter,然后用它来设置页面的标题。 Sounds easy...听起来很容易...
The code:编码:
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.rootRoute(this.route)),
filter((route: ActivatedRoute) => route.outlet === "primary"),
filter(
(route: ActivatedRoute) =>
ComponentWithTitleBase.isPrototypeOf(route.component as any)
),
map((route) => (route.component as unknown) as ComponentWithTitleBase),
tap(console.dir)
)
.subscribe((comp: ComponentWithTitleBase) => {
this.titleSvc.title = comp.title;
});
But the comp.title
is ALWAYS undefined.但
comp.title
始终未定义。 Even though the component does implement get title()
getter:即使组件确实实现了
get title()
getter:
export class AboutComponent extends ComponentWithTitleBase implements OnInit {
get title(): string {
return "About the demo";
}
...
}
I see that console.dir
outputs AboutComponent .我看到
console.dir
输出AboutComponent 。 What am I missing here?我在这里想念什么?
Based on @yurzui's idea, you can use a directive for this:基于@yurzui 的想法,您可以为此使用指令:
@Directive({
selector: 'router-outlet'
})
export class ActivatedComponentsDirective {
constructor(r: RouterOutlet, titleService: TitleService) {
r.activateEvents.pipe(
// takeUntil(r.destroyed),
).subscribe(compInstance => compInstance.title && titleService.newTitle(compInstance.title))
}
ngOnDestroy () {
// destroyed.next;
// destroyed.complete();
}
}
@Injectable({
providedIn: 'root'
})
export class TitleService {
private src = new Subject<string>();
newTitle (t: string) {
this.src.next(t);
}
constructor() { this.initConsumer() }
private initConsumer () {
this.src.pipe(
/* ... */
).subscribe(title => {
console.log('new title', title);
})
}
}
there is a little misunderstanding.有一点误解。 when you console.dir the
.component
you get not an instance of AboutComponent but a class of it.当您 console.dir
.component
您得到的不是 AboutComponent 的实例,而是它的class 。 thus your getter should be static if you want to access it as component.title
因此,如果您想将它作为
component.title
访问,您的吸气剂应该是 static
static get title(): string {
return "About the demo";
}
With the @bespunky/angular-zen library you can do this:使用@bespunky/angular-zen库,您可以这样做:
In the template holding the router outlet:在包含路由器插座的模板中:
<router-outlet publishComponent></router-outlet>
Then, in the component that needs access to the instance:然后,在需要访问实例的组件中:
import { Component } from '@angular/core';
import { NavigationEnd } from '@angular/router';
import { RouteAware } from '@bespunky/angular-zen/router-x';
@Component({
selector : 'app-demo',
templateUrl: './demo.component.html',
styleUrls : ['./demo.component.css']
})
export class DemoComponent extends RouteAware
{
protected onNavigationEnd(event: NavigationEnd): void
{
const currentInstance = this.componentBus.instance();
console.log(`Navigation ended. Current component instance:`, currentInstance )
}
}
It is open-source and you can install the library like this:它是开源的,您可以像这样安装库:
npm install @bespunky/angular-zen
npm 安装@bespunky/angular-zen
Here's a live example with more details. 这是一个包含更多详细信息的实时示例。
If your router outlet has a name, you can pass it to the
instance()
method and retrieve the corresponding outlet's component.如果您的路由器插座有名称,您可以将其传递给
instance()
方法并检索相应插座的组件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.