Angular2'de bir hizmette bir etkinliğe nasıl abone olunur?


112

EventEmitter ile bir olayı nasıl başlatacağımı biliyorum. Bunun gibi bir bileşenim varsa çağrılacak bir yöntem de ekleyebilirim:

<component-with-event (myevent)="mymethod($event)" />

Böyle bir bileşene sahip olduğumda, her şey harika çalışıyor. Bazı mantığı bir hizmete taşıdım ve Hizmetin içinden bir olay oluşturmam gerekiyor. Yaptığım şuydu:

export class MyService {
  myevent: EventEmitter = new EventEmitter();

  someMethodThatWillRaiseEvent() {
    this.myevent.next({data: 'fun'});
  }
}

Bu olaya dayalı olarak bir değeri güncellemem gereken bir bileşenim var, ancak çalışmasını sağlayamıyorum. Denediğim şey şuydu:

//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'ı yükselten hizmet bir bileşen olmadığında etkinliğe abone olmasını nasıl sağlayabilirim?

2.0.0-alpha.28 üzerindeyim

DÜZENLEME: "Çalışma örneğimi" gerçekten işe yarayacak şekilde değiştirdi, böylece çalışmayan kısma odaklanılabilir;)

Örnek kod: http://plnkr.co/edit/m1x62WoCHpKtx0uLNsIv


1
Bu, hizmeti bileşene sıkı bir şekilde bağladığından, bir hizmetin bir bileşen adına olayları yaymaması gerektiğinden, daha çok bir tasarım sorunu olabilir. örneğin, ya bileşenin birden fazla örneği varsa, bu durumda bunların tümü olayları yaymalı mı?
Eğik Üniversitesi

@jhadesdev seni okudum. Çözümü yeniden tasarladım, böylece hizmetin artık sonucu yaymasına gerek kalmadı. Hala bazı tasarımların olayları gündeme getirmekten fayda sağlayamayacağını düşünüyorum - ne tür bir "hizmet" olduğuna bağlı olarak ...
Per Hornshøj-Schierbeck

Bunun bir yolu, bileşenin hizmet yerine olay yayıcıyı oluşturması ve ardından hizmete argüman olarak olay yayıcıyı iletmesi olabilir
Angular University

Yanıtlar:


135

Güncelleme : Bu sorunu bir EventEmitter yerine bir BehaviorSubject veya bir Observable kullanarak çözmek için daha iyi / uygun bir yol buldum. Lütfen şu yanıta bakın: https://stackoverflow.com/a/35568924/215945

Ayrıca, Angular belgelerinde artık Konu kullanan bir yemek kitabı örneği var .


Orijinal / eski / yanlış cevap: yine, bir serviste EventEmitter kullanmayın . Bu bir anti-modeldir.

Beta.1 kullanılıyor ... NavService, EventEmiter'ı içerir. Bileşen Gezinme, hizmetleri hizmet aracılığıyla yayar ve bileşen ObservingComponent olaylara abone olur.

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


Bunu takip ettim ama sadece sınıfın kendisi için çalışıyor. Başka bir sınıf için çalışmıyor (başka bir dosyadan). Görünüşe göre problem servis sınıfı örneğinde. Hizmet sınıfını statik hale getirmenin bir yolu var mı?
asubanovsky

5
@asubanovsky, plunker'da NavService'i yalnızca bootstrap (yani, kök bileşen) düzeyinde enjekte ediyorum, bu nedenle tüm uygulama için hizmetin yalnızca bir örneği olmalıdır. Onu başka bir yere mi enjekte ediyorsunuz providers: [NavService]? Öyleyse, hizmetin birden çok örneğini alacaksınız.
Mark Rajcok

Çok teşekkür ederim. Şimdi beklentim olarak çalışıyor. Şimdi sağlayıcıları bootstrap seviyesinde ve bileşen seviyesinde enjekte etmek arasındaki farkı anlıyorum.
asubanovsky

Bu gönderi, artık 'anlamadığım' bir duruma ciddi şekilde değiştirildi. Neden .getNavChangeEmitter () hizmetinde, EventEmiter'ı navChange'e doğrudan abone olmaktan farklı bir şekilde döndüren bir mehtod çağırılıyor?
Hornshøj-Schierbeck başına

@ PerHornshøj-Schierbeck, hizmet içinde bir EventEmiter'in kullanıldığını gizlemek için getNavChangeEmitter () yöntemini kullandım. Yöntemin kullanıcıları, döndürülen nesnenin bir subscribe()yöntemi olduğunu varsayabilir . Bir yöntem kullanarak, EventEmiter'ı bir Özne veya Gözlemlenebilir olarak kolayca değiştirebiliriz, bu çok daha iyidir, çünkü artık EventEmitters'ın yalnızca Çıktı özellikleri için kullanılması gerektiğini öğrendik. Doğru yol, bir Konu, Davranış Öznesi veya Gözlemlenebilir kullanmaktır ve normalde bunlara doğrudan abone oluruz, dolayısıyla artık bir getNavChangeEmitter () yöntemine ihtiyacımız yoktur.
Mark Rajcok

6

Alfa 28'i kullanarak, eventEmitter.toRx().subscribe(..)yöntem yoluyla olay yayıcılara programlı olarak abone olmayı başardım . Sezgisel olmadığından, gelecekteki bir sürümde değişebilir.


1
belki de insanların bu gönderiye rastladıklarında kullanmaları için basit bir örnek verebilir misiniz? Btw'yi olumsuz oy kullanan ben değildim;)
Per Hornshøj-Schierbeck

2
Neden reddedildiğini bilmiyorum, kesinlikle işe yarıyor. Basitçe söylemek gerekirse, bir etkinlik click.toRx().subscribe(your_callback_function)
yayıcıya

İşleyen bir örneğe sahip olmadığı için reddedilmiş olabileceğini düşünüyorum. Daha iyi sözdizimi görüntülemek için bir pluncker / jsfiddle keman veya kod hatta bazı hatlar için bir bağlantı olsaydı bir upvote ve belki kabul edilen bir cevap değerinde olacağını biliyoruz;)
Başına Hornshøj-Schierbeck

EXCEPTION alıyorum: ReferenceError: tıklama tanımlı değil @ Runeboy Lütfen çözümünüz için bir plnkr sağlayabilir misiniz?
Benjamin McFerren

Çalışması için tıklama adında bir EventEmitter tanımlamanız gerekiyor
Mazen Elkashef
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.