Reputation: 163
I have a parent-child component as below. Inside child.compontent.ts, I have a method : childFunction(). I want to call this method inside parent's function. How to achieve this ?
**Parent.html :**
<div class="box">
<input type="text" (input)="searchValue=$event.target.value" placeholder={{placeHolder}} />
<btn-icon [searchType]='searchType' [searchText]='searchValue'></btn-icon> // child component
</div>
**parent.component.ts :**
export class parentComponent implements OnInit {
parentFunction(){
// **Call** childFunction('inputValue');
}
**btn-icon is Child :**
**btn-icon.component.ts: (Child)**
export class btn-iconimplements OnInit {
@Input() Type: string;
@Input() Text: string;
childFunction(inputValue){
//some logic
}
}
Upvotes: 1
Views: 11496
Reputation: 1
Callback pattern could bring us another solution for this problem. Working solution available on stackblitz: https://stackblitz.com/edit/angular-e6hakq
Child component
@Component({
selector: 'app-child',
template: `<div>
<h3>Child var: {{num}}!</h3>
</div>`,
})
export class ChildComponent implements OnDestroy {
protected num: number = 0;
private _param: ParamFn | null = null;
get param() {
return this._param;
}
@Input() set param(val: ParamFn) {
this._param = val;
this._param.registerFn(this.innerComponentFunction);
}
private innerComponentFunction = () => {
this.num++;
};
ngOnDestroy() {
if (this.param) {
//avoid memory leak
this.param.deregisterFn();
this.param.deregisterFn = null;
this.param.registerFn = null;
}
}
}
export type ParamFn = {
registerFn: (callback: () => void) => void,
deregisterFn: () => void
}
Parent component
@Component({
selector: 'app-parent',
template: `<app-child
[param]="fnParam"></app-child>
<button (click)="invokeChildFn()">Trigger Child Function</button>
`,
})
export class ParentComponent {
private childFn: Function | null = null;
registerDeactivateChildFunction = (func: () => void) => {
this.childFn = func;
};
deregisterFunction = () => {
this.childFn = null;
console.log('deregisterFunction parent');
};
protected fnParam: ParamFn = {
registerFn: this.registerDeactivateChildFunction.bind(this),
deregisterFn: this.deregisterFunction.bind(this),
};
protected invokeChildFn() {
if (this.childFn) {
this.childFn();
}
}
Upvotes: 0
Reputation: 4563
You can inject the Child Component using decorator @ViewChild()
:
@ViewChild(btn-icon)
private btnIcon: btn-icon;
Then you can access its properties like always:
this.btnIcon.childFunction();
Upvotes: 1
Reputation: 350
You should use @ViewChild in the parent component:
export class parentComponent implements OnInit {
@ViewChild(BtnIcon) btnIcon;
parentFunction(){
btnIcon.childFunction();
}
the btnIcon property will only be available and filled with the child component after the ngAfterViewInit() lifecycle hook.
Attention: I used the class name BtnIcon in camelcase and not as "btn-icon" as your example.
Upvotes: 0
Reputation: 57919
just use ViewChild to get the children
export class parentComponent implements OnInit {
@ViewChild(btn-icon) bt-icon //see that viewChild argument is
//the classname of your child-component
parentFunction(){
this.bt-icon.childFunction('inputValue');
}
}
You can also use a template reference and pass as argument to a function, e.g.
<div class="box">
<!--see how, in input event you pass the template reference "child" futhermore
$event.target.value-->
<input type="text" (input)="change(child,$event.target.value)"
placeholder={{placeHolder}} />
<!--see the "#child", it's a template reference-->
<btn-icon #child [searchType]='searchType' [searchText]='searchValue'></btn-icon>
</div>
change(childComponent:bt-icon,value){
chilComponent.childFunction(value)
}
Upvotes: 2