Reputation: 8351
I have one parent page in my angular app where I have implements UI-steps paging with 4 child components.
Parent Component : CustomerMain.ts
BasicDetils.ts
JobDetails.ts
LocationDetils.ts
InsTermsDetails.ts
Based on data fill I am moving forward to next child component and load appropriate data in that component from parent component.
Step 1. Created CustomerMain component and call API to fetch all 4 child component data in single service.
@ViewChild("childBasicDetils")
childBasicDetils: BasicDetils;
@ViewChild("childJobDetails")
childJobDetails: JobDetails;
@ViewChild("childLocationDetils")
childLocationDetils: LocationDetils;
@ViewChild("childInsTermsDetails")
childInsTermsDetails: InsTermsDetails;
viewBasicDetils: boolean = true;
viewJobDetails: boolean = false;
viewLocationDetils: boolean = false;
viewInsTermsDetails: boolean = false;
res: any;
getSFCCustomerDetails(obj) {
this.portService.getSFCCustomerDetails(obj).subscribe(res => {
console.log(res)
this.res = res;
//Fill 1st Component data like below
this.childBasicDetils.customerDetails = this.res.customerDetails;
}
}
Step 2. Load 1st Child component(BasicDetils.ts
) and fill all data related to that component from parent data.
Step 3. Update some record in 1 Child component and press "Next" and load 2nd Child component and try to fill all data from parent.
On Step 3 I am not able to access Child component which I assign through @ViewChild
.
Getting below error:
core.js:1673 ERROR TypeError: Cannot read property 'setJobDataResults' of undefined at AddCustomer.push../src/app/customer/add-customer/add-customer.component.ts.AddCustomer.showHideComponents (add-sweep-customer.component.ts:429) at SafeSubscriber._next (add-customer.component.ts:283) at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:196) at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next (Subscriber.js:134)
I know the reason as at first load all child component not load only 1st component loaded and based on user input I am hiding 1st child component and loading 2nd child component and so on till all child component covered.
Show/Hide Child Components like below:
showHideComponents(index) {
switch (index) {
case 1:
this.viewBasicDetils = true;
this.viewJobDetails = false;
this.viewLocationDetils = false;
this.viewInsTermsDetails = false;
break;
case 2:
this.viewBasicDetils = false;
this.viewJobDetails = true;
this.viewLocationDetils = false;
this.viewInsTermsDetails = false;
case 3:
this.viewBasicDetils = false;
this.viewJobDetails = false;
this.viewLocationDetils = true;
this.viewInsTermsDetails = false;
break;
case 4:
this.viewBasicDetils = false;
this.viewJobDetails = false;
this.viewLocationDetils = false;
this.viewInsTermsDetails = true;
break;
default:
break;
}
}
So basically getting error while calling child component method and passing data like below :
//Fill 2st Component data like below
this.childJobDetails.setJobDataResults(this.res.jobDetails);
My HTML looks like below :
<form class="customForm" *ngIf="viewBasicDetils" style="margin-top: 30px;">
<add-basicdetils #childBasicDetils></add-basicdetils>
</form>
<div *ngIf="viewJobDetails" style="margin-top: 30px;">
<add-jobDetails #childJobDetails [isIncludeCriteria]="true" [isEdit]="isEdit" (onDealIdEmit)="isDealId($event)"></add-jobDetails>
</div>
<div *ngIf="viewLocationDetils" style="margin-top: 30px;">
<add-location-detils #viewLocationDetils [isIncludeCriteria]="false" [isEdit]="isEdit" (addedSLE)="isSLE($event)"></add-location-detils>
</div>
<add-insterms-details #childInsTermsDetails [atcIDCustName]="atcIDCustName" *ngIf="viewInsTermsDetails" (onAtcBackClick)='backCustomerDefinition($event)'></add-insterms-details>
It's always give me undefined component object if i print that ViewChild object.
Please guide me how can I access 2nd child component from Parent.
Thanks In Advance!
Upvotes: 2
Views: 4311
Reputation: 535
Probably not useful to OP anymore, but it may help someone with the same problem.
I had the same problem and I solved it by creating a ViewChildren.
@ViewChildren(MyChildComponent) myViewChilds: QueryList<MyChildComponent>;
Then, I listen to my any changes on my QueryList.
ngAfterViewInit(): void {
this.myViewChilds.changes.subscribe(res => {
// Here I can access my child components.
console.log(res.first);
res.forEach(child => {
console.log(child);
}
});
}
Maybe not the cleanest solution, but at least it lets me keep *ngIf.
Upvotes: 1
Reputation: 10541
If you are using the *ngIf
structural directive from Angular it won't render the element in DOM until the condition is true
, that's the reason you are getting undefined @ViewChild
object.
To solve your issue you can use the hidden
property of HTML where it renders all element in DOM but it won't display to the user.
Example -
<div [hidden]="!viewJobDetails" style="margin-top: 30px;">
<add-jobDetails #childJobDetails [isIncludeCriteria]="true"
[isEdit]="isEdit" (onDealIdEmit)="isDealId($event)"></add-jobDetails>
</div>
Hope this will help!
Upvotes: 1