I've recently discovered Angular Elements and think that could be a very good fit for my portal application which involve many teams with different requirements.
Teams will be responsible for providing their own widgets to other teams. I need to PoC a totally decoupled typed-safe messaging bus between widgets (tile) allowing them to talk to each other.
I started from a very good demo application found on GitHub and added couple of classes. Forked project
Outer world communication is achieved by @Input messageIn and @Output messageOut from inherited BaseWidgetComponent class used by DashboardTileComponent and LazyDashboardTileComponent.
export class BaseWidgetComponent {
private readonly _message: Subject<WidgetMessage>;
constructor() {
this._message = new Subject<WidgetMessage>();
this.messageOut = new EventEmitter<WidgetMessage>();
}
@Input()
set messageIn(message: WidgetMessage) {
this._message.next(message);
}
@Output() messageOut: EventEmitter<WidgetMessage>;
protected on(messageType: string): Observable<WidgetMessage> {
return this._message.pipe(filter(x => x.type === messageType));
}
protected publish(messageType: string, payload: string): void {
this.messageOut.emit({sender: this, type: messageType, payload: payload});
}
}
DashboardComponent (container component) will be responsible to instantiate on runtime widgets and register them using the WidgetMessagingService to enable cross communication. Registration is adding event listener on the messageOut to publish new message and updating the messageIn with new message coming.
public register(widget: NgElement & WithProperties<BaseWidgetComponent>): void {
this._message.subscribe(x => {
widget.messageIn = x;
});
widget.addEventListener('messageOut', (x: CustomEvent<WidgetMessage>) => {
this._message.next(x.detail);
});
}
The problem with this technique, is that there's no mean to know if the widget has been destroy in order to clear all references to avoid leakage.
I tried to add an @Output('destroyed') and emit the event on the OnDestroy lifecycle hook without success.
I found some advanced code sample to intercept all events including 'disconnectedCallback' and do what I except but I wish to keep the code very simple for other devs. Angular Elements bridge
Here you can find My working implementation. You just need to add a default and a lazy widget and click on their publish buttons to see the full flow.
Basically I need to find a way to know when the widget has been disposed and call the unregister method to clear everything.
How can I do that?
Is there any better ways to achieve this communication?