102

I have an app where I have an upload component where I can upload a file. It is embedded in the body.component.

On upload, it should use a function (e.g. BodyComponent.thefunction()) of the parent component (do a call to update the data): but only if it the parent is specifically the body.component. The upload might also be used elsewhere with different behavior.

Something like parent(this).thefunction(), how to do that?

PascalVKooten
  • 20,643
  • 17
  • 103
  • 160

5 Answers5

176

I would create a custom event in the child component. Something like this:

@Component({
  selector: 'child-comp',
  (...)
})
export class ChildComponent {
  @Output()
  uploaded = new EventEmitter<string>();

  uploadComplete() {
    this.uploaded.emit('complete');
  }

Your parent component could register on this event

@Component({
  template `
    <child-comp (uploaded)="someMethod($event)"></child-comp>
  `,
  directives: [ ChildComponent ]
})
export class ParentComponent {
  (...)

  someMethod(event) {
  }
}

Another way would be to inject the parent component in the child one, but they will be strongly linked together...

Srdjan Pazin
  • 103
  • 2
  • 5
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
64

Below is the code that worked for me in the latest

Angular 5+

class ChildComponent {
  @Output() myEvent = new EventEmitter<string>();

  callParent() {
    this.myEvent.emit('eventDesc');
  }
}

In ParentTemplate's template

<child-component (myEvent)="anyParentMethod($event)"
Srdjan Pazin
  • 103
  • 2
  • 5
Shabbir Dhangot
  • 8,954
  • 10
  • 58
  • 80
  • 4
    This is a good solution, because its simple, and the parent decides which method to call. Me like :-) – Jette Aug 02 '18 at 08:47
  • 1
    What if I m using router-outlet? Can i still use (myEvent)? – Robert Williams Oct 27 '18 at 15:32
  • Its for child component used inside parent component. Not sure About router-outlet. May be this question helps you. https://stackoverflow.com/questions/45949476/how-to-call-router-outlet-child-component-method-from-parent-comonent – Shabbir Dhangot Oct 29 '18 at 04:16
39

Solution without events involved.

Suppose that I have a ChildComponent and from that I want to call the method myMethod() which belongs to ParentComponent (keeping the original parent's context).

Parent Component class:

@Component({ ... })
export class ParentComponent {

    get myMethodFunc() {
        return this.myMethod.bind(this);
    }

    myMethod() {
         ...
    }
}

Parent template:

<app-child [myMethod]="myMethodFunc"></app-child>

Child template

@Component({ ... })
export class ChildComponent {

    @Input() myMethod: Function;

    // here I can use this.myMethod() and it will call ParentComponent's myMethod()
}
Francesco Borzi
  • 56,083
  • 47
  • 179
  • 252
  • 1
    I've tried using this but it does not work for me. In my version of myMethod, it references a tabset on the parent component (I'm trying to switch tabs from a child of the parent). When I reference this in the parent, everything works. From the child it's getting into myMethod, but not changing the tab. So I'm wondering if the tabset it is referencing is a copy of the real one when the child is accessing it. I'm not actually sure what's happening here when `this.myMethod.bind(this)` is being returned. (Possibly I'm instead doing something fundamentally wrong.) – Katharine Osborne Dec 20 '18 at 17:55
  • I know but I am not using the 8th version. I need this for Ionic 3 that uses the 5 version. – Vasilis Greece Jun 08 '19 at 14:22
  • @VasilisGreece I'm not sure how to help you, but I strongly suggest you to update to latest Ionic version (currently 4) – Francesco Borzi Jun 08 '19 at 14:32
  • Simplest and most direct way to call the parent's method avoiding unnecessary imports. Using Angular 10 on 2020-11-13. Appreciated. – CPHPython Nov 13 '20 at 10:54
  • This works on 1-27-2022, I tried a lot of other methods including Output() but they all failed but this worked! Thank you, you're brilliant. – LearningCoding Jan 27 '22 at 23:40
24

You can inject the parent component to the child component.

For more details see
- How do I inject a parent component into a child component?
- Angular 2 child component refers to parent component This way you can ensure that thefunction() is only called when parent is a body.component.

constructor(@Host() bodyComp: BodyComponent) {

Otherwise using @Output() is preferred to communicate from child to parent.

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
3

In parent html:

<child [parent]="this"></child>

In child component:

@Input() parent: ParentComponent;
// then do whatever with `this.parent`

Events have their places, but I don't see anything else is simpler than this.