Events in Angular2
During the feed component migration, I encountered code I did not know how to port to Angular 2:
if (!feed.isLocalScreen) {// Until this timeout is reached, the "you are muted" notification// will not be displayed againvar mutedWarningTimeout = now();scope.$on("muted.byRequest", function () {mutedWarningTimeout = secondsFromNow(3);MuteNotifier.muted();});scope.$on("muted.byUser", function () {// Reset the warning timeoutmutedWarningTimeout = now();});scope.$on("muted.Join", function () {mutedWarningTimeout = now();MuteNotifier.joinedMuted();});scope.$watch("vm.feed.isVoiceDetected()", function (newVal) {// Display warning only if muted (check for false, undefined means// still connecting) and the timeout has been reachedif (newVal &&feed.getAudioEnabled() === false &&now() > mutedWarningTimeout) {MuteNotifier.speaking();mutedWarningTimeout = secondsFromNow(60);}});}
When the condition is true, the directive listens for muted.byRequest,
muted.byUser, and muted.Join events. The event-handling code is
straightforward (ignoring $watch for now).
But, wait a minute, I have read the documentation of Angular 2 like a hundred times and I don't remember nothing about "events" with Angular 1.X style. That's because it not exist. Angular 2 don't have a way to make events like in Angular 1, so I have to find a solution. After a search for a solution, I found this entry in laco's blog.
Broadcaster
Basically, the idea is to make a service that implements the $broadcast and
$on a method as we had in $rootScope. To do this we use Observables, very
importants in Angular 2, and for this case, we use a
Subject.
import { Subject } from "rxjs/Subject";import { Observable } from "rxjs/Observable";import "rxjs/add/operator/filter";import "rxjs/add/operator/map";interface BroadcastEvent {key: any;data?: any;}export class Broadcaster {private _eventBus: Subject<BroadcastEvent>;constructor() {this._eventBus = new Subject<BroadcastEvent>();}broadcast(key: any, data?: any) {this._eventBus.next({ key, data });}on<T>(key: any): Observable<T> {return this._eventBus.asObservable().filter((event) => event.key === key).map((event) => <T>event.data);}}
So, now we can start to use events like in the example:
// child.ts@Component({selector: 'child'})export class ChildComponent {constructor(private broadcaster: Broadcaster) {}registerStringBroadcast() {this.broadcaster.on<string>('MyEvent').subscribe(message => {...});}emitStringBroadcast() {this.broadcaster.broadcast('MyEvent', 'some message');}}
How I solved the problem?
I didn't. These events are only to show the user information pop-ups about when he is muted, so it's not a critical feature. By now these events are fired and listen in different components, and some of it still implemented in Angular 1.4.
This is a solution I want to share with you, but I'm not sure if this will be
the way that I will use to solve the problem. Because these events probably
won't be necessary when I reimplement the MuteNotifier.