Search code examples
angulartypescriptangular-ng-ifviewchild

Want to access child component object after parent component loaded based on condition in Angular


I have one parent page in my angular app where I have implements UI-steps paging with 4 child components.

Parent Component : CustomerMain.ts

  • Child Component 1: BasicDetils.ts
  • Child Component 2: JobDetails.ts
  • Child Component 3: LocationDetils.ts
  • Child Component 4: 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!


Solution

  • 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!