-
-
Notifications
You must be signed in to change notification settings - Fork 19
Event Aggregator Use Cases
A typical use case is to use the Event Aggregator as a global pub/sub (publish/subscribe). A user would typically send (publish) data (which could be any type of data) with a key identifier which is used as a Singleton Service and another VM or Service would listen (subscribe) to a particular message sent with a key identifier and do something according to the data received.
// Child (sending user form)
import { EventAggregator } from 'aurelia-event-aggregator';
@inject(EventAggregator)
export class HelloChild{
constructor(private ea: EventAggregator) { }
save(user) {
this.ea.publish('form:saved', user);
}
}
// Parent (listening to user form)
import { EventAggregator, Subscription } from 'aurelia-event-aggregator';
@inject(EventAggregator)
export class HelloParent {
subscription: Subscription;
constructor(private ea: EventAggregator) {
this.subscription = this.ea.subscribe('form:saved', (user) => alert(`Hello ${user.firstName}`));
}
dispose() {
// don't forget to dispose of the subscription to avoid any side effect
this.subscription.dispose();
}
}
Another use case is if we develop a plugin (say a data grid) and we want to have internal communication within that plugin but not outside of it and we also want to make sure that if we reuse the plugin multiple times in a View, then their communications will be contained. A good example would be that if we create 2 grids in a View and the first grid sends a message saying that it cleared all its filters, well we obviously don't want any other grid to react to this message, just the first one (or the originator).
// Plugin
import { EventAggregator, Subscription } from 'aurelia-event-aggregator';
@inject(NewInstance.of(EventAggregator))
export class MyGridPlugin{
subscription: Subscription;
searchFilter = 'something';
constructor(private ea: EventAggregator) {
this.subscription = this.ea.subscribe('filter:cleared', () => this.searchFilter = '');
}
dispose() {
this.subscription.dispose();
}
}
// Service
import { EventAggregator} from 'aurelia-event-aggregator';
@inject(EventAggregator)
export class FilterService {
constructor(private ea: EventAggregator) { }
clear() {
this.ea.publish('filter:cleared', true);
}
}
Very similar to the previous use case, except that not only do we want internal communication, we also want to have global communication. An example of a global communication would be that we want to do a certain action in the plugin when the I18N published a locale changed, for example changing the text of a grid pagination. For that we can use the NewInstance.of(EventAggregator).as(AnotherClass)
, this will allow us to have 2 instance of the Event Aggregator (1 being local to the plugin and the other being a global one).
import { Disposable } from 'aurelia-framework';
/**
* A class that will be used for internal communication of parent-child
* All methods are abstract for typings purposes only
*/
export abstract class PluginEventAggregator {
abstract publish(event: string, data: any): void;
abstract subscribe(event: string, callback: (data: any) => void): Disposable;
}
// Plugin
import { EventAggregator, Subscription } from 'aurelia-event-aggregator';
@inject(
EventAggregator, // Global EA
NewInstance.of(EventAggregator).as(PluginEventAggregator) // Plugin EA
)
export class MyGridPlugin{
subscriptions: Subscription[] = [];
searchFilter = 'something';
constructor(private globalEa: EventAggregator, private pluginEa: PluginEventAggregator) {
this.subscriptions.push(
this.pluginEa.subscribe('filter:cleared', () => this.searchFilter = ''),
this.globalEa.subscribe('i18n:locale:changed', (payload) => this.translatePaginationTexts(payload))
);
}
dispose() {
subscriptions.forEach((subscription: Subscription) => this.subscription.dispose());
}
}
// Service
import { EventAggregator} from 'aurelia-event-aggregator';
@inject(EventAggregator)
export class PaginationService {
constructor(private ea: EventAggregator) { }
clear() {
this.ea.publish('filter:cleared', true);
}
}
In some cases, we maybe want to extend the Event Aggregator and add some functionalities. For example, say we want to know the entire list of subscribe events.
export class ExtendedEventAggregator extends EventAggregator {
subscriberNames: string[] = [];
getAllSubscribedEventNames(): string {
return this.subscriberNames;
}
// override the EA parent method with our own implementation and call the parent method when we're done
// in our demo we'll simply keep track of the event key identifier pushed into an array
subscribe(event: string, callback: (data: any) => void): Disposable {
this.subscriberNames.push(event);
return super.subscribe(event, callback);
}
}
// Parent (listening to user form)
import { EventAggregator, Subscription } from 'aurelia-event-aggregator';
import { ExtendedEventAggregator } from './extendedEventAggregator';
@inject(ExtendedEventAggregator)
export class HelloParent {
subscription: Subscription;
subEventNames: string;
constructor(private extendedEa: ExtendedEventAggregator) {
this.subscription = this.extendedEa.subscribe('form:saved', (user) => alert(`Hello ${user.firstName}`));
}
getSubscribedEvents() {
// should return:: "form:saved"
this.subEventNames = this.ea.getAllSubscribedEventNames().join(', ');
}
dispose() {
this.subscription.dispose();
}
}
Contents
- Aurelia-Slickgrid Wiki
- Installation
- Styling
- Interfaces/Models
- Testing Patterns
- Column Functionalities
- Global Grid Options
- Localization
- Events
- Grid Functionalities
- Auto-Resize / Resizer Service
- Resize by Cell Content
- Add/Delete/Update or Highlight item
- Dynamically Change Row CSS Classes
- Column Picker
- Composite Editor Modal
- Context Menu
- Custom Tooltip
- Excel Copy Buffer
- Export to Excel
- Export to File (CSV/Txt)
- Grid Menu
- Grid State & Presets
- Grouping & Aggregators
- Header Menu & Header Buttons
- Header Title Grouping
- Pinning (frozen) of Columns/Rows
- Row Colspan
- Row Detail
- Row Selection
- Tree Data Grid
- SlickGrid & DataView objects
- Addons (controls/plugins)
- Backend Services