I have two components (1-app-student-list 2-app-student-detail).
I want to use student-detail
in the student-list
like the following :
app-student-detail.html
<p>Student Detail Component is here ....</p>
app-student-detail.ts
export class StudentDetailComponent {
showDetail() {
alert("We are in student-detail...");
}
}
app-student-list.html
<p>Student List Component is here ....</p>
<app-student-detail></app-student-detail>
app-student-list.ts
export class StudentListComponent implements OnInit {
@ViewChild(StudentDetailComponent, { static: true }) studentDetail: StudentDetailComponent;
constructor() { }
ngOnInit() {
}
showDetail() {
this.studentDetail.showDetail();
}
}
In the showDetail
method I want to call a method of StudentDetailComponent
named showDetail
And finally, I want to use student-list in the AppComponent
app.component.ts
export class AppComponent {
public isShow = false;
@ViewChild(StudentListComponent, { static: true }) studentList: StudentListComponent;
title = 'AngualrViewChild';
showDetail() {
this.isShow = true;
this.studentList.showDetail();
}
}
app.component.html
<p>App Component is here ....</p>
<app-student-list *ngIf="this.isShow"></app-student-list>
<hr />
<button type="button" (click)="this.showDetail()">
Show Detail
</button>
When I call the showDetail
method of StudentListComponent
I get the following Error :
AppComponent.html:6 ERROR TypeError: Cannot read property 'showDetail' of undefined
Note: When I remove ngIf
above it will work perfectly
When your student list is not shown (your *ngIf evaluates to false), then your StudentList is also not rendered/available anywhere.
Therefore, your ViewChild can't resolve to anything and the call "this.studentList.showDetail();" won't work. Yes, you changed your boolean value to true, but the changeDetection may not have enough time to run and actually render your StudentList.
In your App.Component, you should also reconsider your :
{ static: true }
Your viewchild, currently, is far from static as it depends on the *ngIf to resolve. Setting it to "static: true" will prevent your ViewChild from updating when your StudentList actually becomes available.
More info about this property.
You have two options here.
For example :
import { Component, OnInit, AfterViewInit, ViewChild } from '@angular/core';
Both should give you the result you are expecting, but before calling child component functions from the parent component, think about WHY you want to do that.
Do you actually want the parent to trigger an action on the children, or do you want the children to do something once he has reached a certain lifecycle ? Most of the time, the logic can be implemented in the children and your parent component can only care about rendering the child or hide it.