Is there no equivalent to $scope.emit()
or $scope.broadcast()
in Angular?
I know the EventEmitter
functionality, but as far as I understand that will just emit an event to the parent HTML element.
What if I need to communicate between fx. siblings or between a component in the root of the DOM and an element nested several levels deep?
My favorite way to do is by using behavior subject or event emitter (almost the same) in my service to control all my subcomponent.
Using angular cli, run ng g s to create a new service then use a BehaviorSubject or EventEmitter
When you do that every component using your service as a provider will be aware of the change. Simply subscribe to the result like you do with eventEmitter ;)
I have created a pub-sub sample here:
http://www.syntaxsuccess.com/viewarticle/pub-sub-in-angular-2.0
The idea is to use RxJs Subjects to wire up an Observer and and Observables as a generic solution for emitting and subscribing to custom events. In my sample I use a customer object for demo purposes
Here is a live demo as well: http://www.syntaxsuccess.com/angular-2-samples/#/demo/pub-sub
DO Not Use EventEmitter for your service communication.
You should use one of the Observable types. I personally like BehaviorSubject.
Simple example:
You can pass initial state, here I passing null
When you want to update the subject
Observe from any service or component and act when it gets new updates.
Here is more information..
There is no equivalent to
$scope.emit()
or$scope.broadcast()
from AngularJS. EventEmitter inside of a component comes close, but as you mentioned, it will only emit an event to the immediate parent component.In Angular, there are other alternatives which I'll try to explain below.
@Input() bindings allows the application model to be connected in a directed object graph (root to leaves). The default behavior of a component's change detector strategy is to propagate all changes to an application model for all bindings from any connected component.
Aside: There are two types of models: View Models and Application Models. An application model is connected through @Input() bindings. A view model is a just a component property (not decorated with @Input()) which is bound in the component's template.
To answer your questions:
What if I need to communicate between sibling components?
Shared Application Model: Siblings can communicate through a shared application model (just like angular 1). For example, when one sibling makes a change to a model, the other sibling that has bindings to the same model is automatically updated.
Component Events: Child components can emit an event to the parent component using @Output() bindings. The parent component can handle the event, and manipulate the application model or it's own view model. Changes to the Application Model are automatically propagated to all components that directly or indirectly bind to the same model.
Service Events: Components can subscribe to service events. For example, two sibling components can subscribe to the same service event and respond by modifying their respective models. More on this below.
How can I communicate between a Root component and a component nested several levels deep?
$scope.broadcast()
from Angular 1. The next section describes this idea in more detail.Example of an Observable Service that uses Service Events to Propagate Changes
Here is an example of an observable service that uses service events to propagate changes. When a TodoItem is added, the service emits an event notifying its component subscribers.
Here is how a root component would subscribe to the event:
A child component nested several levels deep would subscribe to the event in the same way:
Here is the component that calls the service to trigger the event (it can reside anywhere in the component tree):
Reference: Change Detection in Angular