Angular-在路由器事件中获取组件实例

时间:2020-07-27 20:15:23

标签: angular typescript angular-routing

我正在尝试为我的angular 10应用程序提供标题服务。我需要订阅路由器事件,获取激活的路由的组件,看看它是否实现title() getter,然后使用它来设置页面的标题。听起来很简单...

代码:

    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;
      });

但是comp.title始终未定义。即使该组件确实实现了get title() getter:

export class AboutComponent extends ComponentWithTitleBase implements OnInit {
  get title(): string {
    return "About the demo";
  }

  ...
}

我看到console.dir输出 AboutComponent 。我在这里想念什么?

3 个答案:

答案 0 :(得分:1)

基于@yurzui的想法,您可以为此使用指令:

activated-component.directive.ts

class SearchBar: UISearchBar {

    var activityIndicator: UIActivityIndicatorView?
    
    var isLoading: Bool {
        get {
            return activityIndicator != nil
        } set {
            if newValue {
                if activityIndicator == nil {
                    
                    guard let leftView = searchTextField.leftView else {
                        return
                    }
                    
                    let ai = UIActivityIndicatorView(style: .medium)
                    ai.frame = convert(leftView.frame, from: leftView.superview)
                    addSubview(ai)
                    
                    ai.startAnimating()
                    leftView.isHidden = true
                    activityIndicator = ai
                    
                }
            } else {
                activityIndicator?.removeFromSuperview()
                activityIndicator = nil
                
                guard let leftView = searchTextField.leftView else {
                    return
                }
                leftView.isHidden = false
            }
        }
    }
    
}

title.service.ts

@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();
  }
}

ng-run demo

答案 1 :(得分:0)

有些误解。当您使用console.dir .component时,您不会获得AboutComponent的实例,而是它的。 因此,如果您想以component.title

的方式访问它,则您的getter应该是静态的
static get title(): string {
  return "About the demo";
}

答案 2 :(得分:0)

使用@bespunky/angular-zen库,您可以执行以下操作:

在保存路由器出口的模板中:

<router-outlet publishComponent></router-outlet>

然后,在需要访问实例的组件中:

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 )
    }
}

它是开源的,您可以像这样安装库:

npm install @ bespunky / angular-zen

Here's a live example,具有更多详细信息。

?如果路由器插座具有名称,则可以将其传递给instance()方法,并检索相应插座的组件。