I created a really simple angular PubSubService in TypeScript, to allow communication between controllers or directives or services.
In the example below, controller 1, fires an event and controller 2 reacts to the firing of the event.
module dev {
"use strict";
var appModule = angular.module("myApp", []);
appModule.controller("MyController1", ["$scope", "pubSubService", ($scope, pubSubService)
=> new dev.MyController1($scope, pubSubService)]);
appModule.controller("MyController2", ["$scope", "pubSubService", ($scope, pubSubService)
=> new dev.MyController2($scope, pubSubService)]);
export class MyController1 {
constructor(public $scope: ng.IScope, public pubSubService: PubSubService) {
// Fire an an event
pubSubService.publish("my-custom-event", "some publisher data");
}
}
export class MyController2 {
constructor(public $scope: ng.IScope, public pubSubService: PubSubService) {
this.handleMyCustomEvent = this.handleMyCustomEvent.bind(this);
// Subscribe to be notified, when "my-custom-event" is fired.
pubSubService.subscribe("my-custom-event", this.handleMyCustomEvent);
}
handleMyCustomEvent(data: any) {
// Do something, when an event is fired from MyController1.
}
}
/**
* This service can be used to share data between controllers by using a pub sub mechanism.
*/
export class PubSubService {
private nextListenerIndex: number;
private listeners: Array<IListener>;
constructor() {
this.listeners = [];
this.nextListenerIndex = 0; // The first subscription will be located at index 0;
this.publish = this.publish.bind(this);
this.subscribe = this.subscribe.bind(this);
this.unsubscribe = this.unsubscribe.bind(this);
}
/**
* Publish an event.
* All subscribers will be notified.
* @param name, is the name of the event and is case insensitive.
*/
publish(name: string, data?: any) {
for (var i = 0, length = this.listeners.length; i < length; i++) {
const listener = this.listeners[i];
if (listener && listener.name.toLowerCase() === name.toLowerCase()) {
listener.handler.call(null, data, listener.subData);
}
}
}
/**
* Subscribe to be notified, when an event is published.
* @param name, is the name of the event and is case insensitive.
* @returns A token, that can be used to unsubscribe.
*/
subscribe(name: string, handler: (data?: any, subData?: any) => void, data?: any): number {
var token = this.nextListenerIndex;
this.listeners[token] = {
handler: handler,
name: name,
subData: data
};
this.nextListenerIndex += 1;
return token;
}
/**
* Remove the event listener subscription.
* @param token received on subscribing to an event listener.
*/
unsubscribe(token: number) {
// This will create holes in the array, but for now we do not care.
this.listeners[token] = null;
}
}
export interface IListener {
// This function will be called when an event is published.
// Data is the data from the publisher, subData is the data from the subscriber.
handler: (data?: any, subData?: any) => void;
name: string;
subData?: any; // Data from the subscriber.
}
angular.service("pubSubService", () => new PubSubService());
}