Child listens for parent event in Angular 2

61,843

Solution 1

I think that this doc could be helpful to you:

In fact you could leverage an observable / subject that the parent provides to its children. Something like that:

@Component({
  (...)
  template: `
    <child [parentSubject]="parentSubject"></child>
  `,
  directives: [ ChildComponent ]
})
export class ParentComponent {
  parentSubject:Subject<any> = new Subject();

  notifyChildren() {
    this.parentSubject.next('some value');
  }
}

The child component can simply subscribe on this subject:

@Component({
  (...)
})
export class ChildComponent {
  @Input()
  parentSubject:Subject<any>;

  ngOnInit() {
    this.parentSubject.subscribe(event => {
      // called when the notifyChildren method is
      // called in the parent component
    });
  }

  ngOnDestroy() {
    // needed if child gets re-created (eg on some model changes)
    // note that subsequent subscriptions on the same subject will fail
    // so the parent has to re-create parentSubject on changes
    this.parentSubject.unsubscribe();
  }

}

Otherwise, you could leverage a shared service containing such a subject in a similar way...

Solution 2

For the sake of posterity, just thought I'd mention the more conventional solution to this: Simply obtain a reference to the ViewChild then call one of its methods directly.

@Component({
  selector: 'app-child'
})
export class ChildComponent {

  notifyMe() {
    console.log('Event Fired');
  }
}

@Component({
  selector: 'app-parent',
  template: `<app-child #child></app-child>`
})
export class ParentComponent {

  @ViewChild('child')
  private child: ChildComponent;

  ngOnInit() {
    this.child.notifyMe();
  }
}

Solution 3

A more bare bones approach might be possible here if I understand the question correctly. Assumptions --

  • OP has a save button in the parent component
  • The data that needs to be saved is in the child components
  • All other data that the child component might need can be accessed from services

In the parent component

<button type="button" (click)="prop1=!prop1">Save Button</button>
<app-child-component [setProp]='prop1'></app-child-component>

And in the child ..

prop1:boolean;
  @Input()
  set setProp(p: boolean) {
    // -- perform save function here
}

This simply sends the button click to the child component. From there the child component can save the data independently.

EDIT: if data from the parent template also needs to be passed along with the button click, that is also possible with this approach. Let me know if that is the case and I will update the code samples.

Share:
61,843
Hamed Hamedi
Author by

Hamed Hamedi

Updated on May 25, 2020

Comments

  • Hamed Hamedi
    Hamed Hamedi almost 4 years

    In angular docs there is a topic about listening for child events from parents. That's fine. But my purpose is something reverse!. In my app there is an 'admin.component' that holds the layout view of admin page (sidebar menu,task bar, status etc..). In this parent component I configured router system for changing the main view between other pages of administrator. The problem is for saving things after change, the user clicks on save button in task bar (that is placed in admin.component) and the child component must listen to that click event for doing save staff.

  • kind user
    kind user about 7 years
    It crashes as soon as I enter the parent component... Cannot read property 'notifyMe' of undefined.
  • Stephen Paul
    Stephen Paul about 7 years
    Hm, apparently your child component is not being set by Angular. Make sure that ChildComponent has the correct selector.
  • jwanglof
    jwanglof about 7 years
    Awesome, unlike the accepted answer this solution doesn't require any extra lib (even though RxJS is standard for Angular2 =))
  • cjsimon
    cjsimon about 7 years
    The callback in my child component won't run unless the parent component broadcasts the next value from within ngInit. Why is that the case?
  • cjsimon
    cjsimon almost 7 years
    When the child component is initialized after the parent component, my child reference is undefined. Is there a way to wait for it to be initialized before assigning the ViewChild?
  • sunnyiitkgp
    sunnyiitkgp almost 7 years
    Are there any advantages of using this method over ViewChild?
  • user3777549
    user3777549 over 6 years
    I tried for a day to get a child component to get updated by its parent component via subscribing to a shared service with no luck, this solution is so simple! Thank you!
  • Lijo
    Lijo over 6 years
    multiple child using same commponent then this will fail
  • Stephen Paul
    Stephen Paul over 6 years
    @Lijo good point. It's been a while since I looked at this. Updated my ViewChild() decorator to rather target the #id rather than the component type.
  • Bernoulli IT
    Bernoulli IT about 6 years
    Although it looks more professional, after giving it some hours to experiment with in my situation I couldn't get out of trouble with UnsubscribeErrors upon adding / removing child elements (and thus unsubscribing from the topic). So by means of TimeBoxing I went for the much more straightforward answer of @StephenPaul. Anyway thanks for the answer and probably I just don't get the rxjs library well enough right now to fully understand it and make the right (extra) adjustments to your example to have it work flawless.
  • Bernoulli IT
    Bernoulli IT about 6 years
    Went for this very straighforward solution as compared to the somehow more professional feeling solution of @ThierryTemplier (see my comment there).
  • Stephen Paul
    Stephen Paul about 6 years
    @BernoulliIT you make a good point. I suppose at the end of the day they accomplish roughly the same thing. My solution uses less code. His solution means that the parent component doesn't have to inject the child component to send it messages. RXJS is great, but I do often see overuse of it within Angular projects. People think its this 'silver bullet' or something. It can actually make things much more complicated than they need to be. Look at his comment inside his ngOnDestroy() method. That's way too obscure as far as I'm concerned. That's just a bug waiting to happen IMHO.
  • Bernoulli IT
    Bernoulli IT about 6 years
    "Look at his comment inside his ngOnDestroy() method." I think that's exactly what I was "suffering" from when trying that approach, then I got stuck and didn't have that much time to investigate any further (for a commercial project I work on). Although it "hurted' my professional heart a bit ;)
  • Khuram
    Khuram about 6 years
    Thanks @StephenPaul, for me Parent Calls a Viewchild method was good, but your answer helped me to reach my destiny!