I will not waste any time writing the merits of Angular- we all know, it is the best. However, are you suffering from having to manage a lot of obscure data bindings between components and having to re-propagate them to alert grandparents? Do you want to make the components talk to each other irrespective of where they are in the component hierarchy? Do you want them to talk to each other regardless they are loaded dynamically or when they are behind routes?
Well — you are not alone.
The Problem
The preferred means of data flow between components is data bindings. The preferred function triggering mechanism between components is event triggers. This serves very well for communication between a parent and a child component.
Things start to get complicated when the inter-component communication wants to span beyond the limits of immediate parent — child relationship. Imagine you have a component hierarchy like this one:
It is one of those common setups where you have a deep hierarchy of components.
Imagine the green scenario (1) where the NewOrder Component wants to notify its parent, the OrderManager component, of the occurrence that the user successfully created an order.
With Angular this is simple. The NewOrder Component will have an @output property and a place to emit the event.
@Output() newOrderEvent = new EventEmitter<number>();
...
...
this.newOrderEvent.emmit(this.lastOrderId);
and the OrderManager parent component will have the event binding.
<new-order (newOrderEvent)=”showId($event)”></new-order>
Pretty neat huh?
Now let’s imagine the red scenario (2) where the NewOrder component has to reach all the way through to the HomeComponent! Worst still, even to the SideBar component. Sadly, Angular events wouldn’t propagate themselves all the way to the root component. The event needs to be captured in each stage and propagate again to the immediate parent — again at each level.
Needless to say that in practicality, the above diagram would be crisscrossing with arrows. Multiple event handlers and event bindings in each template would maroon you in an unimaginable forest of event names and bind functions that just do one thing — propagate events and propagate them further.
Ng-Interconnect to the rescue
The Ng-Interconnect is a seamless connector. It connects any component with any other in a single line of code and lets one component trigger events in any other without any barrier. If you wish to go even beyond that by wanting to make one component trigger events in multiple other components, Ng-Interconnect can do that with a single line of code. Still not enough? If your use case is making one component to listen to multitude of other components, Ng-Interconnect is ready — and just needs a single line of code again. The list is not over yet. But let’s go by example.
Installation:
npm install ng-interconnect...import {Interconnect} from 'ng-interconnect';...constructor(private interconnect: Interconnect) {
}
Let’s see how the NewOrder component can tell the HomeComponent that a brand new order is just created — without any binding.
In new-order.component.ts:
//Create the broadcaster in the constructor / initializer
this.orderAnnouncement = this.interconnect.createBroadcaster(‘newOrderCreated’);…
//Somewhere down when an order is created
this.orderAnnouncement.emmit(this.lastId)
In home.component.ts:
this.interconnect.receiveFrom(‘newOrderCreated’, ‘home’, () => {
console.log(‘thanks!’)
})
Really that’s all. No @output @input properties, no event capturing in the template, no Foo no Bar!
Here are cool facts about where the above short example can go:
- It doesn't matter which component is created first — HomeComponent or the NewOrderComponent. Ng-Interconnect will just work.
- The broadcaster name can accept namespaces — “home/orders/new”. This makes it easier to quickly identify in code where the broadcasting is expected from
- The HomeComponent can make the callback shared by many broadcasters by supplying an array of them. Ex:
this.interconnect.receiveFrom([‘newOrderCreated’, 'orderEdited', 'orderDeleted'] , ‘home’, () => {
console.log(‘thanks!’)
})
Here is this example in action: https://stackblitz.com/edit/angular-ivy-km5jxq
This app talks to a sibling and a grandparent in a single command without having any data or event binding.
Capabilities of ng-interconnect
- Works across routes without any special configuration
- Works on dynamically loaded components
- Create broadcasters — data from one point to many destinations
- Create listeners — data from many points to a single destination
- RegEx matching of destinations
- Not affected by the component creation order
- Create a promise in any component and resolve to any other
- Fully compatible with observables — all methods support data, error, and complete states.
Official documentation and the library: