简体   繁体   English

Angular 2 - 如何在没有模板的情况下收听事件?

[英]Angular 2 - How to listen to event without a template?

The Problem 问题

Normally, in Angular 2, one would listen to an event via the following syntax: 通常,在Angular 2中,可以通过以下语法监听事件:

<my-elem (customEvent)="customEventProcessor"></my-elem>

But when I use a router, that host - <my-elem> - does not exist in any template. 但是当我使用路由器时,该主机 - <my-elem> - 在任何模板中都不存在。 Instead, there's a <router-outlet> , and my component is loaded upon navigation. 相反,有一个<router-outlet> ,我的组件在导航时加载。 Thus, the crux of my problem is, How can I force my host to listen to my custom event without relying on a template? 因此,我的问题的关键是, 如何在不依赖模板的情况下强制我的主机听我的自定义事件?

Optional Details 可选细节

Suppose I have some element list-view , which is a child of my root component. 假设我有一些元素list-view ,它是我的根组件的子元素。 list-view listens for a custom event via the normal syntax: list-view通过常规语法侦听自定义事件:

<list-view (customEvent)="customEventProcessor()"></list-view>

Just for completeness, the list-view component that emits the event also has a predictable structure: 为了完整起见,发出事件的list-view组件也具有可预测的结构:

<button (click)="onDetailsClick(propertyOfInterest)">Click here</button>

The list-view sends the event up to the parent via observation. list-view通过观察将事件发送到父级。

class ListView {

    ...

        public onDetailsClick(property: string): void {

            this.customEvent.next({ value: property });

        }

}

and that event triggers the customEventProcessor() function. 并且该事件触发customEventProcessor()函数。 So far so good. 到现在为止还挺好。 However, when I use a router to control whether list-view is present, I cannot (to my knowledge) insert a command to monitor some event. 但是,当我使用路由器来控制是否存在list-view ,我不能(据我所知)插入命令来监视某些事件。

I am not sure what the best approach is to handle this case. 我不确定处理这种情况的最佳方法是什么。

This problem isn't resolved yet (see this github issue ). 此问题尚未解决(请参阅此github问题 )。 Here is one of the possible solutions at this moment (see this plunk ): 这是目前可能的解决方案之一(见本文 ):

@Component({
  selector: 'my-app',
  directives: [RouterOutlet, RouterLink],
  template: `
    <h1>{{ message }}</h1>
    <a [router-link]="['./MyElem1']">MyElem1</a>
    <a [router-link]="['./MyElem2']">MyElem2</a>
    <router-outlet></router-outlet>
  `
})
@RouteConfig([
  { path: '/', redirectTo: '/my-elem1' },
  { path: '/my-elem1', name: 'MyElem1', component: MyElem1 },
  { path: '/my-elem2', name: 'MyElem2', component: MyElem2 },
])
export class App {
  message: string = 'Click on the button';

  @ViewChild(MyElem1) myElem1: MyElem1;
  @ViewChild(MyElem2) myElem2: MyElem2;

  constructor(router: Router) {
    let subs = null;
    router.subscribe(() => {
      if (subs) { subs.unsubscribe(); subs = null; }

      if (this.myElem1) {
        subs = this.myElem1.customEvent1.subscribe(m=>this.processCustomEvent(m));
      }
      if (this.myElem2) {
        subs = this.myElem2.customEvent2.subscribe(m=>this.processCustomEvent(m));
      }
    });
  }

  processCustomEvent(message) { this.message = message }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM