19
votes

I have a Submitbutton in the parent component namelypersonDetails.personDetailshas manyperson` components. Whenever I click on the Submit button, I want to call a method in child component.

How can I emit an event from a parent to a child component using @Output?

Its easy to do it from the child to the parent. I want to access a value of the child component, hence I need to emit an event from parent to child.

2

2 Answers

39
votes

You can create one service which is shared between your parent and child component in which you can define Observable so that you can subscribe to that Observable from child and perform some action when you receive some value from parent.

//common.service.ts

import { Injectable, Inject } from '@angular/core';
import { Subject }    from 'rxjs/Subject';
@Injectable()
export class CommonService {
  private notify = new Subject<any>();
  /**
   * Observable string streams
   */
  notifyObservable$ = this.notify.asObservable();

  constructor(){}

  public notifyOther(data: any) {
    if (data) {
      this.notify.next(data);
    }
  }
}

//parent.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

import { CommonService } from './common.service';

@Component({
  selector   : 'parent',
  templateUrl : './parent.html'
})
export class ParentComponent implements OnInit, OnDestroy {
  constructor( private commonService: CommonService ){
  }

  ngOnInit() {
    this.commonService.notifyOther({option: 'call_child', value: 'From child'});
  }
}

//child.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

import { CommonService } from './common.service';

@Component({
  selector   : 'child',
  templateUrl : './child.html'
})
export class ChildComponent implements OnInit, OnDestroy {
  private subscription: Subscription;
  constructor( private commonService: CommonService ){
  }

  ngOnInit() {
    this.subscription = this.commonService.notifyObservable$.subscribe((res) => {
      if (res.hasOwnProperty('option') && res.option === 'call_child') {
        console.log(res.value);
        // perform your other action from here

      }
    });
  }

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

Child Component

In childComponent.ts

@Input() private uploadSuccess: EventEmitter<boolean>;

Additionally in childComponent.ts subscribe to the event:

ngOnInit() {
  if (this.uploadSuccess) {
    this.uploadSuccess.subscribe(data => {
      // Do something in the childComponent after parent emits the event.
    });
  }
}

Parent Component

In ParentComponent.html

<app-gallery  [uploadSuccess] = "uploadSuccess" > </app-gallery>

In ParentComponent.ts

private uploadSuccess: EventEmitter<boolean> = new EventEmitter();

onImageUploadSuccess(event) {
   console.log('Image Upload succes');
   if (event.code === 'OK' && this.maxUploadLimit > 0) {
      this.galleryImagesCount = this.galleryImagesCount + 1;
      this.maxUploadLimit = this.maxUploadLimit - 1;
    }

   // The parent emits the event which was given as `@Input` variable to the child-component
   this.uploadSuccess.emit(true);
}