6
votes

In an Angular 2 app, say i have a 'SaveComponent' where clicking its save button calls a function isDirty() that returns true or false (true if the content of the parent component has been modified). Note the reason for the 'SaveComponent' is that it has styles and other 'widgets' associated with it that are shared among many components.

currently there is a isDirty function defined in each of the parent components, and the function is passed to SaveComponent as follows inside the parent template:

<save-component [isDirty]="isDirty"> </save-component>

if you care to see, a simplified version of SaveComponent is defined something like this...

import {Component, Input} from 'angular2/core';

@Component({
  selector: 'save-component',
  templateUrl: 'who-cares-to-know.component.html'
})

export class SaveComponent {
  @Input() isDirty;
}

It works only initially. It seems that the isDirty function only returns false (or only called once?) even when the content is modified. Note that the function does work correctly when it's called from the parent component.

What's wrong? Is it possible to pass function from parent to child component via @Input or some other means? Thanks!

2
Are you doing [(ngModel)]="isDirty" on a textbox or something to update your value? (On the parent component that is) - Mark Pieszak - Trilon.io

2 Answers

8
votes

The problem is that you lose the context of your method when referencing it, i.e. the "this" keyword.

I would use something like that:

getIsDirty() {
  return () => {
    return this.isDirty();
  }
}

With the arrow function, you will be able to use the lexical this. The latter corresponds to the component instance itself.

And provide it to the sub component this way:

<save-component [isDirty]="getIsDirty()"> </save-component>
1
votes

I realize this is old, but I just ran into the issue so hopefully this can help someone moving forward. I also tried to edit the first answer but that was rejected, and I don't have enough reputation to comment on the first answer.

The first answer is correct, but it's not complete. In order to call the parent function in the child component you need to treat @Input() isDirty as a function as opposed to a property.

Call this.isDirty() as opposed to this.isDirty in order to run the function.