2015-06-30 3 views
60

Я знаю, как поднять событие с помощью EventEmitter. Я могу также прикрепить метод, который будет вызываться, если у меня есть компонент, как это:Как подписаться на мероприятие на службе в Angular2?

<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

EDIT: Модифицированная мой «рабочий пример» на самом деле работает, поэтому фокус может быть поставлен на не-рабочей части;)

Пример код: http://plnkr.co/edit/m1x62WoCHpKtx0uLNsIv

+1

Это может быть больше вопрос дизайна, как услуга не должны испускать события от имени компонент, так как это тесно связывает службу с компонентом. например, что, если есть несколько экземпляров компонента, должны ли они все испускать события в этом случае? –

+0

@jhadesdev Я тебя читал. Я сделал редизайн решения, поэтому службе больше не нужно испускать результат. Я по-прежнему думаю, что некоторые проекты не могут быть связаны с возможностью поднять события - в зависимости от того, какая «услуга» это ... –

+0

в одном случае может возникнуть необходимость создания компонента вместо источника службы, а затем передать событие-эмитент в качестве аргумента для службы –

ответ

78

Обновление: Я нашел лучший/правильный способ решить эту проблему, используя BehaviorSubject или Observable, а не EventEmitter. Пожалуйста, см. Этот ответ: https://stackoverflow.com/a/35568924/215945

Кроме того, Угловые документы теперь имеют cookbook example that uses a Subject.


Оригинал/устаревшие/неправильный ответ: снова, don't use an EventEmitter in a service. Это анти-шаблон.

Использование бета-версии 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); 
    } 
} 

Plunker

+0

Я следил за этим, но он работает только для самого класса. Он не работает для другого класса (из другого файла). Кажется, что проблема заключается в экземпляре класса обслуживания. В любом случае, чтобы класс обслуживания стал статичным? – asubanovsky

+3

@asubanovsky, в [plunker] (http://plnkr.co/edit/wzN7ZKU1CmVwbtxw8XFJ?p=preview) Я только внедряю NavService на уровне начальной загрузки (то есть, корневого компонента), поэтому должен быть только один экземпляр сервис для всего приложения. Вы вводите его в другом месте «поставщиками: [NavService]»? Если это так, вы получите несколько экземпляров службы. –

+0

спасибо. Сейчас он работает как мое ожидание. Теперь я понимаю разницу между инъекцией поставщиков на уровне начальной загрузки и на уровне компонентов. – asubanovsky

3

Используя альфа 28, я выполнил программную подписку на излучатели событий с помощью метода eventEmitter.toRx().subscribe(..). Поскольку это не интуитивно, возможно, это может измениться в будущей версии.

+1

, возможно, представляет собой простой пример использования людьми, если они наткнулись на этот пост?Это был не я, нигде, ни в коем случае;) –

+2

Не знаю, почему это было отклонено, это, безусловно, работает. Проще говоря, чтобы подписаться на «эмитент» события, нажмите 'click.toRx(). Subscribe (your_callback_function)' – Runeboy

+0

Я думаю, что это могло быть опущено, потому что в нем не хватает рабочего примера? Я знаю, что это было бы достойным продолжением и, возможно, принятым ответом, если бы у него была ссылка на скрипт pluncker/jsfiddle или даже некоторые строки кода, чтобы лучше отображать синтаксис;) –

Смежные вопросы