Reputation: 692
One can use Output()
decorator to emit the event from the child component so that the parent component can catch it. What I need is to catch an event emitted by any child component, which is not necessarily a direct child of a given component.
Let ComponentTwo
be a component which emits the event. If the app has the following structure: App -> ComponentTwo
, then we can easily catch the event emitted by ComponentTwo
. But if we consider structure like App -> ComponentOne -> ComponentTwo
, then we can't catch the emitter directly.
Here is a plunker that illustrates the problem.
So is there a way to sort of propagate event to all parent components? Thanks.
Upvotes: 16
Views: 18703
Reputation: 146218
If you find you have to pass certain events through make sure to be consistent and come up with a naming strategy. For instance I like to add raise
to the beginning of the method name if the only thing that method does is to re-raise an event.
eg.
(paypalTokenized)="raisePaypalTokenized($event)"
and in the ts
file:
@Output('paypalTokenized')
public paypalTokenizedEmitter = new EventEmitter<PayPalTokenizedPayload>();
// PayPal tokenized
public raisePaypalTokenized(payload: PayPalTokenizedPayload)
{
// no other logic here!
this.paypalTokenizedEmitter.emit(payload);
}
This means I can tell immediately that the event is being passed through with no further action.
Upvotes: 1
Reputation: 33
the thierry answer is the correct aproach, but if you want to avoid use shared service, you can do somthing like this
view.html
<componentA
(actionA)=actionHandler($event)
>
</componentA>
view.ts
actionHandler(event){
//doSomething
}
componentA.html
<componentB
(actionB)=actionHandlerA($event)
>
</componentB>
componentA.ts
@Output() actionA: EventEmitter<{}> = new EventEmitter();
constructor() {
}
actionHandlerA(event){
this.actionA.emit(event);
}
componentB.html
<a (click)="actionHandlerB(...)" >click me</a>
componentB.ts
@Output() actionB: EventEmitter<{}> = new EventEmitter();
constructor() {
}
actionHandlerB(o: objectModel){
this.actionB.emit(new objectModel(o));
}
Upvotes: 0
Reputation: 202346
There is no support of bubbling for such events. You need to manually catch them and emit to the parent.
Another approach would be to leverage a shared service for this tree of components and use an observable / subject in it.
This way all components can subscribe on it to be notified of events even within sub sub children.
constructor(private service: SharedService) {
this.service.notifier$.subscribe(
data => {
(...)
});
}
The event will be triggered this way:
constructor(private service: SharedService) {
}
notify() {
this.service.notifier$.next('some data');
}
See this link for more details:
Upvotes: 27