3

Angular 2 version: rc.1

I have a parent and a child component.

I have an object called Options in the parent component containing strings and functions I want to pass to the child component using @Input. The strings that I pass work fine and as expected, but I am having trouble passing a function.

Here is some of the code relating to my problem.

parent.component.ts

  constructor(private service: Service) {}
  //getResults is a function in service that takes two arguments
  public Options = {
    placeholder: "Enter Value",
    getReq: function(foo, bar) {
      return this.service.getResults(foo, bar)
    }, 

parent.component.html

<child placeholder="{{Options.placeholder}}" getReq="{{Options.getReq}}"><child>

child.component.ts

  @Input() placeholder: String;
  @Input() getReq: Function;

  searchResults() {
    return this.getReq(foo, bar)
      .subscribe(
        data => this.Results$ = data
      )
  }

The error I get is "this.getReq is not a function"

Any ideas?

Eric Scandora
  • 121
  • 2
  • 7

1 Answers1

3

getReq={{Options.getReq}} will assign the function as a string to child property getReq because {{expression}} always converts the expression to a string. This explains your error.
You can also console.log(typeof this.getReq) to see that it is a string.

Passing parent functions to the child results in tightly coupling the parent component to the child, which is normally not recommended. Ideally, the child should not know anything about the parent. This makes the (child) component more reusable.

Instead of your current approach, either

  • inject the service into the child, and have the child call the service method, or
  • add an output property/EventEmitter to the child and have the child call myOutputProperty.emit([foo, bar]). The parent can then call the method on the service. When the service returns data, "send" it back down to the child using an input property on the child. (You don't have to "send" it, just set the parent property that is bound to the input property, and Angular change detection will automatically propagate the new value down to the child input property).

See also related SO questions

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • depending on what parent component I am using with this child component, I will be using different services, so I was hoping to do something like this to make this child component more reusable and neutral. Does that make sense? Any thoughts how that could be done? – Eric Scandora May 20 '16 at 02:59
  • @EricScandora, you could pass some kind of ID down to the child. When the child `emit()`s an event, include that ID. The parent could then map that ID to the appropriate function and call it. – Mark Rajcok May 20 '16 at 05:11
  • Although it might not be the best practice, Michael Liu's comment on my post worked perfectly for what I am trying to do. Just to let you know in case you want to include it in your answer. – Eric Scandora May 20 '16 at 14:40
  • 1
    Thanks, but I still don't recommend that. I believe you could have problems with the `this` context, depending on what the function tries to do. – Mark Rajcok May 20 '16 at 14:44