0
votes

My goal is, from the child component, I want to call a method in the parent and get the return value. I tried the following approach but was not successful.

In parent.html

<child-component [config]="getConfig(data)"></child-component>

In parent.ts

data = <some data>
...
getConfig(val) {
    // format value and return
    return formattedVal;
}

In child.ts

@Input() config: Function
...
retrieve() {
    const conf = this.config();
}

I am getting an error "this.config is not a function"

Also, I tried using EventEmitter but this time, it returned "undefined"

In parent.html

<child-component (config)="getConfig(data)"></child-component>

In child.ts

@Output() config = new EventEmitter();
...
retrieve() {
    const conf = this.config.emit;
}
3
why do you want to do this? your getConfig method returns a config and send it to child, why are you want to get the function? you need to get the config. stackblitz.com/edit/angular-dgt2xf - Fateme Fazli
i need to do this because of the following: the child is subscribed to an observable. when it's triggered, the child will get a new set of config.. This new set of config is the result of the parent doing formatting on the original config. - iPhoneJavaDev
Also, I don't want the child to know how the config is formatted. It just need to get the config by calling this function. I also don't want the parent to be triggering a method in the child. - iPhoneJavaDev
if the config is triggered just in child why are you sending it from parent? trigger the observable in parent format the data and send it to child. - Fateme Fazli
the child component is reusable. for example, the parent has a grid list containing several of this child component. when the observable is triggered, these child components should be able to reload their data. but they need their config from the parent. i don't want the child to know how to format this config, they just need to get the latest config from parent. if i simply send it to child, how will i tell the child to reload its data? - iPhoneJavaDev

3 Answers

1
votes

Inject ParentComponent to ChildComponent and call the function as below:

In your ChildComponent.ts,

constructor(public parentComponent: ParentComponent) {}

In your ChildComponent.html,

<child-component [config]="parentComponent.getConfig(data)"></child-component>
0
votes

you defined config as Function but this.config is just formattedVal which is just value and defined from parent.ts

and EventEmitter is usually used when you want to pass value from child to parent. not to pass from parent to child


So you can get the value from parent.ts directly

in this case, this value is formattedVal as I mentioned above

in child.ts

@Input() config
...
retrieve() {
    const conf = this.config;
}
0
votes

Basically what you want to do is pass a function to a child and do anything with it. so for example from the parent component you have a 'returnRandom' function which returns a random number with a cap of what ever the user pass on the function however sadly you might need to put your data into a global scope.

Parent Component TS

import { Component } from '@angular/core';

const parentGlobalVar = 10;

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  parentLocalVar = 0;


  public returnRandom(max: number): number {
    console.log(parentGlobalVar); // logs '10'
    console.log(this.parentLocalVar); // logs 'undefined'
    return Math.floor(
      Math.random() * max + 1
    );
  }

}

and then pass the function to the child component at the html tag

<app-child [parentFn]="returnRandom"></app-child>

then call the function to the Child component and do whatever you want from it.

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.scss']
})
export class ChildComponent implements OnInit {

  @Input() parentFn: Function;

  constructor() { }

  ngOnInit() {
    console.log(this.parentFn( 100 ));
  }

}