Reputation: 33992
In an Angular 2+ component, how do I pass in a callback function that takes parameters? My initial assumption was something like
<app-example [onComplete]="doThing('someParam')"></app-example>
And sometimes I won't need any parameters, like this:
<app-example [onComplete]="doSomeThingElse()"></app-example>
And then in the component I have
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
})
export class ExampleComponent {
@Input() public onComplete: () => void;
//run `this.onComplete()` somewhere as needed
}
But, what ends up happening is that the doThing('someParam')
or doSomeThingElse()
is immediately called without any interaction.
How am I supposed to pass callback functions in to a component to be called later?
The actual problem I am trying to solve here is to be able to run any passed in function at a later time. This is for a confirmation component that will ask the user "are you sure you want to continue?" and then if they press the "Yes I'm sure" button, the passed in function will run.
Upvotes: 19
Views: 70733
Reputation: 76
The said solution will work only if you have a method that needs to invoke without taking action on the component itself. However, in my case, I need to execute an observable method inside of the app-example component and wait for the response to do some action inside of that component.
If anyone has the same issue. Here is the solution for it.
create an interface.
export interface Delegate<T> {
(...args: any[]): T;
}
On your angular component, create a @Input
variable
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
})
export class AppExampleComponent {
@Input() executeWhen: Delegate<Observable<any>>;
runOnComplete(): void {
this.executeWhen().subscribe(() => // do some action);
}
}
Upvotes: 4
Reputation: 15211
Template:
<app-example [someParams]="someParamsObject"
(complete)="onComplete($event)" >
</app-example>
Component:
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
})
export class ExampleComponent {
@Input()
someParams: YourParamsType;
@Output()
complete:EventEmitter<any> = new EventEmitter<any>();
//run `this.complete(this.someParams)` somewhere as needed and
//pack in some params if you need
}
In your calling, parent component you need a function named onComplete
that receives parameter of type any
in this case (that comes from @Output
being defined as EventEmitter<any>
). If you need, you can also have event parameters of any particular type you like EventEmitter<YourParticularType>
.
Upvotes: 4
Reputation:
Here's an example of the @Output
syntax @toskv was looking for, Angular pass callback function to child component as @Input
So for your example,
<app-example
(onComplete)="doThing()"
[completedParam]="'someParam'"></app-example>
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
})
export class ExampleComponent {
@Output() public onComplete: EventEmitter<any> = new EventEmitter();
@Input() completedParam;
runOnComplete(): void {
this.onComplete.emit(this.completedParam);
}
}
Does not feel as good as [onComplete]="doThing.bind(this, 'someParam')"
.
Upvotes: 26
Reputation: 8011
You can have a private method in your component:
private doThingFactory(param) {
return () => this.doThing(param);
}
and then use it like that:
<app-example [onComplete]="doThingFactory('someParam')"></app-example>
Upvotes: 1