如何在 Angular2 中订阅服务事件?
How to subscribe to an event on a service in Angular2?
我知道如何使用 EventEmitter 引发事件。如果我有这样的组件,我还可以附加一个要调用的方法:
<component-with-event (myevent)="mymethod($event)" />
当我有这样的组件时,一切都很好。我将一些逻辑移到了服务中,我需要从服务内部引发一个事件。我所做的是:
export class MyService {
myevent: EventEmitter = new EventEmitter();
someMethodThatWillRaiseEvent() {
this.myevent.next({data: 'fun'});
}
}
我有一个组件需要根据此事件更新一些值,但我似乎无法让它工作。我试过的是:
//Annotations...
export class MyComponent {
constructor(myService: MyService) {
//myService is injected properly and i already use methods/shared data on this.
myService.myevent.on(... // 'on' is not a method <-- not working
myService.myevent.subscribe(.. // subscribe is not a method <-- not working
}
}
当引发事件的服务不是组件时,如何让 MyComponent 订阅事件?
我在 2.0.0-alpha.28
编辑:修改了我的 "working example" 以实际工作,因此可以将重点放在不工作的部分上;)
使用 alpha 28,我通过 eventEmitter.toRx().subscribe(..)
方法以编程方式完成了对事件发射器的订阅。由于它不直观,它可能会在未来的版本中改变。
Update:我找到了 better/proper 方法来使用 BehaviorSubject 或 Observable 而不是 EventEmitter 来解决这个问题。请看这个答案:
此外,Angular 文档现在有一个 cookbook example that uses a Subject。
Original/outdated/wrong 再次回答:,。那是一个反模式。
使用 beta.1... NavService 包含 EventEmiter。组件导航通过服务发出事件,组件 ObservingComponent 订阅事件。
nav.service.ts
import {EventEmitter} from 'angular2/core';
export class NavService {
navchange: EventEmitter<number> = new EventEmitter();
constructor() {}
emitNavChangeEvent(number) {
this.navchange.emit(number);
}
getNavChangeEmitter() {
return this.navchange;
}
}
components.ts
import {Component} from 'angular2/core';
import {NavService} from '../services/NavService';
@Component({
selector: 'obs-comp',
template: `obs component, item: {{item}}`
})
export class ObservingComponent {
item: number = 0;
subscription: any;
constructor(private navService:NavService) {}
ngOnInit() {
this.subscription = this.navService.getNavChangeEmitter()
.subscribe(item => this.selectedNavItem(item));
}
selectedNavItem(item: number) {
this.item = item;
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
@Component({
selector: 'my-nav',
template:`
<div class="nav-item" (click)="selectedNavItem(1)">nav 1 (click me)</div>
<div class="nav-item" (click)="selectedNavItem(2)">nav 2 (click me)</div>
`,
})
export class Navigation {
item = 1;
constructor(private navService:NavService) {}
selectedNavItem(item: number) {
console.log('selected nav item ' + item);
this.navService.emitNavChangeEvent(item);
}
}
我知道如何使用 EventEmitter 引发事件。如果我有这样的组件,我还可以附加一个要调用的方法:
<component-with-event (myevent)="mymethod($event)" />
当我有这样的组件时,一切都很好。我将一些逻辑移到了服务中,我需要从服务内部引发一个事件。我所做的是:
export class MyService {
myevent: EventEmitter = new EventEmitter();
someMethodThatWillRaiseEvent() {
this.myevent.next({data: 'fun'});
}
}
我有一个组件需要根据此事件更新一些值,但我似乎无法让它工作。我试过的是:
//Annotations...
export class MyComponent {
constructor(myService: MyService) {
//myService is injected properly and i already use methods/shared data on this.
myService.myevent.on(... // 'on' is not a method <-- not working
myService.myevent.subscribe(.. // subscribe is not a method <-- not working
}
}
当引发事件的服务不是组件时,如何让 MyComponent 订阅事件?
我在 2.0.0-alpha.28
编辑:修改了我的 "working example" 以实际工作,因此可以将重点放在不工作的部分上;)
使用 alpha 28,我通过 eventEmitter.toRx().subscribe(..)
方法以编程方式完成了对事件发射器的订阅。由于它不直观,它可能会在未来的版本中改变。
Update:我找到了 better/proper 方法来使用 BehaviorSubject 或 Observable 而不是 EventEmitter 来解决这个问题。请看这个答案:
此外,Angular 文档现在有一个 cookbook example that uses a Subject。
Original/outdated/wrong 再次回答:,
使用 beta.1... NavService 包含 EventEmiter。组件导航通过服务发出事件,组件 ObservingComponent 订阅事件。
nav.service.ts
import {EventEmitter} from 'angular2/core';
export class NavService {
navchange: EventEmitter<number> = new EventEmitter();
constructor() {}
emitNavChangeEvent(number) {
this.navchange.emit(number);
}
getNavChangeEmitter() {
return this.navchange;
}
}
components.ts
import {Component} from 'angular2/core';
import {NavService} from '../services/NavService';
@Component({
selector: 'obs-comp',
template: `obs component, item: {{item}}`
})
export class ObservingComponent {
item: number = 0;
subscription: any;
constructor(private navService:NavService) {}
ngOnInit() {
this.subscription = this.navService.getNavChangeEmitter()
.subscribe(item => this.selectedNavItem(item));
}
selectedNavItem(item: number) {
this.item = item;
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
@Component({
selector: 'my-nav',
template:`
<div class="nav-item" (click)="selectedNavItem(1)">nav 1 (click me)</div>
<div class="nav-item" (click)="selectedNavItem(2)">nav 2 (click me)</div>
`,
})
export class Navigation {
item = 1;
constructor(private navService:NavService) {}
selectedNavItem(item: number) {
console.log('selected nav item ' + item);
this.navService.emitNavChangeEvent(item);
}
}