Home > OS >  How to emit an event from child to parent to another child?
How to emit an event from child to parent to another child?

Time:11-15

I'm having a child component that get some data from a form. And passes that to a parent component via the @Output decorator. Pressing a button triggers getDataFromForm()

export class FormChildComponent {

    @Output() doSomethingWithData: EventEmitter<any> = new EventEmitter<any>()

    ...

    getDataFromForm(){
        ...

        this.doSomethingWithData.emit(form.values);
        
    }
    renderSomething(?data){
       //This needs to be called in anther child after the event got 
       triggered and the data got processed in the parent

    }

}

In the parent component i'm doing some processing with the data, on the button press event in the child. After that i have to render something based on the processed data in another child, wich is the same child component type as above.

parent.component.html

<FormChildComponent (doSomethingWithData)="processData($event)">

parent.component.ts

processData($event: object){
    
    doSomething($event);

} 

Whats the best practice to pass events and data between childs and their parent?

CodePudding user response:

You should just define an variable on the child and use @Input() decorator. E.g.: @Input() prop: YourType;.

Then you can pass data from the parent to the child by using:

<FormChildComponent [prop]="dataToPassToChild" (doSomethingWithData)="processData($event)">

This is usually the best practice in order to pass data from parent to child components. The other way around was already included in your question (using @Output() decorator).

There are some cases where you want to extract some properties in an independent state. You should use a service in order to achieve this.

CodePudding user response:

Dealing with inputs and outputs on multiple components can get messy, I prefer to just create a service to emit and subscribe from events.

@Injectable({ providedIn: 'root' })
export class MyService {
  dataSubject = new Subject<DataType>();
}

Just inject the service wherever you need it, call next on the subject to emit the event, and subscribe to the subject where you want to act on the events.

To emit

export class ChildOneComponent {
  data = 'someData';

  constructor(private myService: MyService) {}

  emit() {
    this.myService.dataSubject.next(this.data);
  }
}

To act on the event

export class ChildTwoComponent {
  subscription = new Subscription();

  constructor(private myService: MyService) {}

  ngOnInit() {
    this.subscription = this.myService.dataSubject.subscribe(this.processData);
  }

  processData(data: DataType) {
    console.log('Got: ', data);
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

I know you said the child components are the same type, so I'm not sure exactly what your code looks like, considering the components are doing two different things. You might need to elaborate.

Is it two components that are subscribed to eachother? Is it one way where one component is subscribed to the other but not vise versa? Is it a list of components that are subscribed arbitrarily to each other? etc.

  • Related