Angular2 passing function as component input is not working
18,344
Solution 1
You need to .bind(this)
if you pass methods around:
<custom-element [valFn]="customVal.bind(this)"></custom-element>
or
export class App {
constructor(private service: CustomService) {
}
customVal(): string {
return this.service.getVal();
}
customValFn = this.customVal.bind(this);
}
with
<custom-element [valFn]="customValFn"></custom-element>
Solution 2
You can pass a get/set property instead of a function in a similar way like that:
Somewhere in your view:
<input type="text" [(ngModel)]="yourprop">
In your component file:
@Component({
selector: 'myapp',
templateUrl: './myapp.component.html',
styleUrls: ['./myapp.component.scss']
})
export class App {
constructor() { }
yourprop: any;
get yourprop(): any {
return this.scheduleEndDate;
};
//set accessor including call the onchange callback
set yourprop(v: any) {
// TODO do something else
// You can do whatever you want just like you have passed a function
if (v !== this.scheduleEndDate) {
this.scheduleEndDate = v;
}
}
}
more info @ https://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel
Author by
Ashok Koyi
Updated on June 17, 2022Comments
-
Ashok Koyi about 2 years
I've a component that takes function as input. I've passed this function from parent.
Though the function is called, the function is not able to access the dependencies of the instance on which this function is declared.
Here is the component
@Component({ selector: 'custom-element', template: ` {{val}} ` }) export class CustomElement { @Input() valFn: () => string; get val(): string { return this.valFn(); } }
Here is how the component is used
@Injectable() export class CustomService { getVal(): string { return 'Hello world'; } } @Component({ selector: 'my-app', template: ` <custom-element [valFn]="customVal"></custom-element> `, }) export class App { constructor(private service: CustomService) { } customVal(): string { return this.service.getVal(); } }
When I run this app, I get an error in the console saying
Cannot read property 'getVal' of undefined
Here is a plunker for the issue.
-
Ashok Koyi over 7 yearsThanks :). That works. I thought the context on which this function is run is already set as it is referred on the
App
instance -
Ashok Koyi over 7 yearsAny idea on why
this
context is lost in case of function, whereas it can refer to correctthis
incase of properties? -
Günter Zöchbauer over 7 yearsThis is "normal" ;-) or "default" JS behavior. If you pass methods or functions around that refer to
this
, you have to either use.bind(this)
or arrow functions (like[valFn]="() => customVal()"
but that's not supported in template bindings AFAIR. -
Günter Zöchbauer over 7 yearsThe "default" behavior is that
this
points to the caller of the function, not the declarer. -
Ankit over 6 yearsI want to add one more thing, if you inject CustomerService into your custom-element component then it will work fine, in that case you need not to bind this explicitly. @gunter is right BTW, this holds the context of the current class not the class where method is declared.
-
Steve about 6 yearsIs this preferred, ie. why not setup an emitter ?
-
Günter Zöchbauer about 6 years@Steve event binding is definitly preferred if possible, but if someone asks for passing methods I try to answer that.
-
Yukun almost 6 yearsHi @GünterZöchbauer, if an emitter is the preferred solution, can you please provide an example? or any reference? thank you
-
Günter Zöchbauer almost 6 years@Yukun is there an Angular introductorial that doesn't explain
@Output()
withEventEmitter
?