1

In Angular 2 you work a lot with this, which is fine but I've found that it also creates an issue when you want to pass down a function down the component hierarchy.

Take this for example:

export class ParentComponent {

  myFunctionFromParent() {
    this.isActive = true;
  }
}

Then we pass this function down to a child:

<parent>
  <child [onClick]="myFunctionFromParent"></child>
</parent>

And let's say child is a simple button:

<button (click)="onClick()"></button>

Now, when myFunctionFromParent runs, this should be the ParentComponent but it's not.

Instead it's the ChildComponent that will have it's this.isActive property changed.

This creates a lot of issues as you can't execute parent functions from a child component and expect the parent properties to change.

Passing down functions works as you would expect them to do in Angular 1, but now it seems broken.

Is this no longer the way to do things like this? What is the correct way to to this in Angular 2?

Chrillewoodz
  • 27,055
  • 21
  • 92
  • 175
  • FYI....you can access parent's function from child component. – micronyks Apr 11 '16 at 07:44
  • have you heard of `Injector`? using Injector you can inject parent component into child and then child can call any parent's function. – micronyks Apr 11 '16 at 07:55
  • @micronyks You're right, I did see an answer like that.. But when creating abstract components it's not the best method however. In specific scenarios then I guess it would be. Thanks for the reminder. – Chrillewoodz Apr 11 '16 at 07:58

2 Answers2

1

I would use this instead:

<parent>
  <child (onClick)="myFunctionFromParent()"></child>
</parent>

and define an @Output in the child component:

@Component({
  selector: 'child',
  template: `
    <button (click)="onClick()"></button>
  `
})
export class ChildComponent {
  @Output('onClick')
  eventHandler:EventEmitter<any> = new EventEmitter();

  onClick() {
    this.eventHandler.emit();
  }
}
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • What would the output return? Can you give an example of what you mean? – Chrillewoodz Apr 11 '16 at 07:43
  • Hmm.. Not sure I understand what's happening here. Isn't `myFunctionFromParent` being called instantly rather than when I click the button? – Chrillewoodz Apr 11 '16 at 07:46
  • In fact, `onClick` must be a custom event for the `child` component. To implement a custom event, you need to have an `@Output` in the component (associated with a property of type `EventEmitter`). To trigger the event, you need to call its `emit` method. In this case, the expression you register in the parent component against the event will be executed. – Thierry Templier Apr 11 '16 at 07:51
  • The `onClick` event isn't a native event so you need to handle it by yourself – Thierry Templier Apr 11 '16 at 07:51
  • Interesting, that does make things a lot simpler. Will have some changes to do in my components then, cheers :) – Chrillewoodz Apr 11 '16 at 07:55
1

Instead of passing functions around use default Angular data binding with inputs and outputs:

class ParentComponent {
  myFunctionFromParent() {
    this.isActive = true;
  }  
}
class ChildComponent {
  @Output() onClick = new EventEmitter();
}
<parent>
  <child (onClick)="myFunctionFromParent()"></child>
</parent>
<button (click)="onClick.emit()"></button>
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567