0

I know there are many questions with accepted answers in stackoverflow. But I didn't find the one which I am looking for.

I have one parent html and then importing another html from parent. I am getting the list in parent.ts and passing to to the child. Then when I use the list in child html, I am getting this.

Any help would be greatly appreciated.

Error:

ERROR TypeError: Cannot read property '0' of undefined
    at Object.eval [as updateDirectives] (QuarterDataComponent.html:5)

dashboard.component.ts

dashboardDataList: Dashboard[];

  ngOnInit() {
      this.selectedLineId = sessionStorage.getItem("LINE_ID");
      if(this.selectedLineId === undefined || this.selectedLineId === null) {
          alert("Please select Line in 'Configuration' tab");
          this.router.navigate(['/configuration']);
      } else {
          this.populateDashboardData();
      }
  }

      populateDashboardData() {
              this.dashboardService
                  .getDashboardData(1, 101, this.fromDatetime, this.toDatetime)
                      .subscribe(dashboardDataList => this.dashboardDataList = dashboardDataList);
          }

dashboard.component.html

<div style="height:100%;">
    <app-quarter-data [dashboardDataList]="dashboardDataList"></app-quarter-data>
</div>

quarter-data.component.ts @Component({ selector: 'app-quarter-data', templateUrl: './quarter-data.component.html', styleUrls: ['./quarter-data.component.css'] }) export class QuarterDataComponent {

    @Input() dashboardDataList: Dashboard[];

  ngOnInit() {
      alert("1...");
  }

} quarter-data.component.html (Error from the code dashboardDataList[0] )

<fieldset class="scheduler-border" [ngClass]="dashboardDataList[0].isCurrentQuarter==true ? 'current-quarter-true' : 'current-quarter-false'">
                <div class="quarterTopDiv">
                    <table  class="quarterTopTable table-sm table-striped" appearance="border">
                        <thead>
                          <tr>
                            <th>Associate #</th>
                            <th>Sequence #</th>
                          </tr>
                        </thead>
                        <tbody >
                          <tr *ngFor="let installedPartView of dashboardDataList[0].installedPartViewList let index=index; let odd=odd; let even=even">
                            <td>{{installedPartView.associateId}}</td>
                            <td [tooltip]="'[' + installedPartView.productId + ']\n [' + installedPartView.partName + ']'" placement="top" show-delay="500">{{installedPartView.afOnSequenceNo}}</td>
                          </tr>
                        </tbody>
                    </table>
                </div>

</fielsdet>

dashboard.service.ts

getDashboardDataByLineAndProcess(assNo: number, processId: string, fromDatetime: string, toDatetime: string) { return this.http .get(this.serviceUrl+'defect-result-data-for-dashboard/'+ assNo+ '/' + processId+'/' + fromDatetime + '/' + toDatetime) .map(response => { const array = response.json() as Dashboard[]; return array; }) .catch((error: any) => { if (error._body) { const errorBody = JSON.parse(error._body); this.alertService.error(errorBody.message); } else { this.alertService.error(error); } return Observable.throw(error.statusText); }); }

REST Service output:

[{
    "quarter": 1,
    "isCurrentQuarter": true,
    "noOfDefects": 3,
    "target": 0,
    "lineId": null,
    "installedPartViewList": [{
        "defectResultId": 2000009918,
        "productId": "VAN GUARD",
        "partName": "AIR SHUTTLE",
        "partId": null,
        "partSerialNumber": "A1",
        "actualTimestamp": "2019-03-06T21:17:32.773+0000",
        "quarter": 1,
        "associateId": "userid    ",
        "productionDate": null,
    }, {
        "defectResultId": 2000009919,
        "productId": "SUN PH",
        "partName": "AIR SHUTTLE",
        "partId": null,
        "partSerialNumber": "A1",
        "installedPartStatus": 1,
        "measurementStatus": null,
        "actualTimestamp": "2019-03-06T21:17:32.773+0000",
        "quarter": 1,
        "associateId": "userid    ",
        "productionDate": null,
    }, {
        "defectResultId": 2000009920,
        "productId": "SUM HOS",
        "partName": "AIR SHUTTLE",
        "partId": null,
        "partSerialNumber": "A1",
        "installedPartStatus": 1,
        "measurementStatus": null,
        "actualTimestamp": "2019-03-06T21:17:32.773+0000",
        "quarter": 1,
        "associateId": "userid    ",
        "productionDate": null,
    }],
    "defectResultViewList": [{
        "defectResultId": 2000009918,
        "productId": "BOA",
    }, {
        "defectResultId": 2000009919,
        "productId": "PHONE RT",

    }, {
        "defectResultId": 2000009920,
        "productId": "SUN PH",
    }],
    "processAssociateViewList": null,
    "associateSummaryViewList": null
}, {
    "quarter": 2,
    "isCurrentQuarter": null,
    "noOfDefects": 0,
    "target": 0,
    "lineId": null,
    "installedPartViewList": [],
    "defectResultViewList": null,
    "processAssociateViewList": null,
    "associateSummaryViewList": null
}, {
    "quarter": 3,
    "isCurrentQuarter": null,
    "noOfDefects": 0,
    "target": 0,
    "lineId": null,
    "installedPartViewList": [],
    "defectResultViewList": null,
    "processAssociateViewList": null,
    "associateSummaryViewList": null
}, {
    "quarter": 4,
    "isCurrentQuarter": null,
    "noOfDefects": 0,
    "target": 0,
    "lineId": null,
    "installedPartViewList": [],
    "defectResultViewList": null,
    "processAssociateViewList": null,
    "associateSummaryViewList": null
}]
3
  • The input data array is simply not populated at the time you are trying to access [0]. You can use ngIf at the level of the parent to only render the child component once data has been async resolved or checks in the child to check for length before attempting to access index 0 of that array. Commented Mar 5, 2019 at 22:52
  • when do you call populateDashboardData? If you call it after the child component was initialised, your dashboardDataList is null until then and hence trying to get the first element of that list would give you the null pointer exception. Commented Mar 5, 2019 at 22:53
  • @Erbsenkoenig: Added some new code and explained the problem in below answer's comment Commented Mar 6, 2019 at 15:06

2 Answers 2

1

The template is being rendered before it receives the data. You can wrap the child component in a <ng-container> and use an *ngIf directive to only display once the dashboardDataList is resolved.

<ng-container *ngIf="dashboardDataList">
    ...
    <fieldset class="scheduler-border" [ngClass]="dashboardDataList[0].isCurrentQuarter==true ? 'current-quarter-true' : 'current-quarter-false'">
    </fielsdet>
    ...
</ng-container>
Sign up to request clarification or add additional context in comments.

7 Comments

Yes, you are right. The quarter-data.html is rendering before the list initializes. But I am wondering why... I added some more code. The intention is to redirect to Configuration page if a Line is not selected. So that means quarter-data is not supposed to render before. But now I am getting the alert which is in quarter-data.html and then it is redirecting to Configuration html
the line this.dashboardService.getDashboardData(...) is asynchronous and is being resolved after the view is rendered. The *ngIf is being re-evaluated when changes occur (example, when your async data is resolved) and re-renders your template.
this.dashboardService.getDashboardData(...) has been called from this.populateDashboardData(). And this.populateDashboardData() is inside else block. I am wondering when I am redirecting to 'Configuration' page inside if block, why it is still rendering quarter-dat.html.... any idea?
I tried adding <ng-container *ngIf="dashboardDataList"> , but no luck, same error
@SK. Can you add your full html templates? The error has to do with dashboardDataList being undefined/not resolved but need more to determine the issue.
|
0

I would like you to two things, 1)Implement AfterViewInit to populate child component instead of ngOnInit() 2)Have *ngIf condition in the parent component

1 Comment

@SK did you resolve the issue ? If yes i am just curious to know how?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.