Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How pass a event from deep nested child to parent in Angular 2?

I have a nested child component that have a output Event, I want listen this event from parent component but I dont know how, I have 4 levels:

I tried to pass the event from child 3 to child 2 and child 2 to child and to Parent, but I think that this is not the best way.

-Parent (From this I want listen the event)
--Child
----Child 2
------Child 3 (This have the Event)
like image 1000
juanjinario Avatar asked May 24 '19 10:05

juanjinario


2 Answers

Though you can use an @Output event emitter to do this, I'd suggest that you create a shared service instead that will handle the communications since there are quite many levels of nesting.

You can do something like below, and inject the service in both of your components. One will emit the message (your nested child component), and one will listen for the messages (your top level component).

Define your service

@Injectable({
    providedIn: 'root'
})
export class CommunicationService {
    @Output() message$: EventEmitter<boolean> = new EventEmitter();

    sendMessage(message: String) {
        this.change.emit(message)
    }
}

Inject it in your components

constructor(private communicationService: CommunicationService) { }

In the component where you will send the message from

sendMessage() {
    this.communicationService.sendMessage('This is a message from deep below!');
}

And in your listener component, subscribe to the event emitter

ngOnInit() {
    this.communicationService.message$.subscribe(message => {
      console.log(message);
    });
}
like image 108
Daniel B Avatar answered Sep 17 '22 18:09

Daniel B


Source Dan Wahlin (ng-conf: Mastering the Subject: Communication Options in RxJS ), it's not recommanded to use OutPut when you have a component in a deeper level that has to communicate with a higher lever component , imagine you have 5 or 6 leves!!, you have to use Subject instead: you can create and Event bus through an observable service

Events here is an enum of events if you want

export enum Events{
 'payment done',
  // other events here
 }

@Injectable()
export class EventService {

 private subject$ = new Subject()

 emit(event: EmitEvent) {
    this.subject$.next(event); 
  } 

 on(event: Events, action: any): Subscription {
 return this.subject$.pipe(
  filter((e: EmitEvent) => e.name == event),
  map((e: EmitEvent) => e.value)).subscribe(action);
 }

}

so now imagine that you want to emit an event from Child3 , let's say for example after a payment is done => notify parent component

export class Child3Component implements OnInit {

  constructor(public eventservice : EventService ) {}
  pay(paymentAmount: any) {
    this.eventservice.emit(
      new EmitEvent('payment done',paymentAmount));
  }
}

now in your parent component you can call on method like this and you will get the event

 export class ParentComponent implements OnInit {
   constructor(public eventservice : EventService ) {}
   ngOnInit() {
    this.eventservice.on('payment done', (paymentAmount => console.log(paymentAmount));
   }
 }
like image 20
Fateh Mohamed Avatar answered Sep 17 '22 18:09

Fateh Mohamed