Events in Angular2
About how to migrate events from AngularJS to Angular2.
During the migration of the feed component, I found some lines that I didn't know how to code it on Angular 2. The following code is an extract of the code I'm talking about:
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);}});}
As you can see in the snippet, if the condition is true then the directive
listens for events of type muted.byRequest
, muted.byUser
and muted.Join
.
The code that involves this events is easy, without any type of complexity (for
now we ignore the $watch
).
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
.