简体   繁体   中英

Angular - Cannot Read Property '..' of undefined

in my Angular project, I'm getting an error that says "cannot read property of '...' of undefined" where the '...' is the index of whichever employee that is selected from the combo box.

A little background on my project. I have the user select an employee from a combo box (tracker.component). Then, then index of that employee is taken and used to display the information of that employee (summary.component). It works great, along with having next, previous, first, last buttons but whenever I open the summary panel (summary.component) I get the error that I stated above in the browser. Where am I messing up?

Here's my tracker.component.ts

 import { Component, OnInit, Input} from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { PTODataService } from './pto-data.service'; import { PTOData } from './pto-data'; import { EmpInfoService } from './emp-info.service'; import { EmpInfo } from './emp-info'; @Component({ selector: 'pto-tracker', templateUrl: `./tracker.component.html`, styleUrls: ['./tracker.component.css'] }) export class TrackerComponent implements OnInit{ empInfo: EmpInfo[] = new Array<EmpInfo>(); ptoData: PTOData[]; isHidden: boolean = false; selectedEmployee: number = 0; public selectedType: string = "PTO"; constructor( private empInfoService: EmpInfoService, private ptoDataService: PTODataService) { } getEmpInfo(): void { this.empInfoService.getEmpInfos().then( empInfo => { this.empInfo = empInfo.sort((a, b) => a.LastName < b.LastName ? -1 : b.LastName < a.LastName ? 1 : 0); }); } getPTOData(): void { this.ptoDataService.getPTODatas().then( ptoData => this.ptoData = ptoData ); } ngOnInit(): void { this.getEmpInfo(); this.getPTOData(); } toggleSummary(): void { this.isHidden = !this.isHidden; } isNextValid() { if (this.selectedEmployee > 0) { return true; } else { return false; } } isPreviousValid() { if (this.selectedEmployee < this.empInfo.length - 1) { return true; } else { return false; } } nextEmployee(): void { this.selectedEmployee = this.selectedEmployee + 1; } previousEmployee(): void { this.selectedEmployee = this.selectedEmployee - 1; } firstEmployee(): void { this.selectedEmployee = 0; } lastEmployee(): void { this.selectedEmployee = this.empInfo.length - 1; } } 

my tracker.component.html

 <div class="row"> <div [ngClass]="{'col-xs-12':isHidden === true, 'col-xs-7': isHidden !== false}"> <button class="btn btn-default btn-primary" style="width:50px; height: 50px; float:right; padding-bottom: 10px; padding-top: 10px;margin:5px;" (click)="toggleSummary()"><i class="fa fa-pencil-square-o fa-2x" aria-hidden="true"></i></button> <div class="col-xs-12 no-pad" style="padding-bottom:50px;"> <div class="col-xs-3"> <select class="form-control" id="empName" [(ngModel)]="selectedEmployee"> <option selected="selected" disabled>Employee Name...</option> <option *ngFor="let emp of empInfo; let i = index" [ngValue]="i">{{i}} {{emp.EmpID}} - {{emp.FirstName}} {{emp.LastName}}</option> </select> </div> <div class="col-xs-2"> <select class="form-control" id="PTOtype" [(ngModel)]="selectedType"> <option selected="selected" value="PTO">PTO</option> <option value="etoEarned">ETO - Earned</option> <option value="etoUsed">ETO - Used</option> <option value="STDLTD">STD/LTD</option> <option value="Uncharged">Uncharged</option> </select> </div> </div> <div class="col-xs-12"> <table class="table table-striped table-bordered"> <thead> <tr> <th>Date</th> <th>Full/Half</th> <th>Hours</th> <th>Scheduled?</th> <th>Notes</th> <th>In P/R?</th> </tr> </thead> <tfoot *ngIf="empInfo && empInfo.length > selectedEmployee"> <tr> <td colspan="6"> <span class="requestText">Requests:</span> <button class="btn btn-default btn-primary btn-bargin" style="float: right;" (click)="lastEmployee()"><i class="fa fa-step-forward fa-lrg" aria-hidden="true"></i></button> <button [disabled]="!isPreviousValid()" class="btn btn-default btn-primary btn-margin" style="float:right;" (click)="nextEmployee()"><i class="fa fa-play fa-lrg" aria-hidden="true"></i></button> <div class="footertext">{{selectedEmployee+1}} of {{empInfo.length}}</div> <button [disabled]="!isNextValid()" class="btn btn-default btn-primary btn-margin" style="float: right;" (click)="previousEmployee()"><i class="fa fa-play fa-flip-horizontal fa-lrg" aria-hidden="true"></i></button> <button class="btn btn-default btn-primary btn-margin" style="float: right;" (click)="firstEmployee()"><i class="fa fa-step-backward fa-lrg" aria-hidden="true"></i></button> </td> </tr> </tfoot> <tbody> <tr *ngFor="let pto of ptoData"> <ng-container *ngIf="pto.type === selectedType"> <ng-container *ngIf="pto.EmpKey === empInfo[selectedEmployee].EmpKey"> <td>{{pto.date | date: 'MM/dd/y'}}</td> <td>{{pto.fullhalf}}</td> <td>{{pto.hours}}</td> <td>{{pto.scheduled}}</td> <td>{{pto.notes}}</td> <td>{{pto.inPR}}</td> </ng-container> </ng-container> </tr> </tbody> </table> </div> </div> <div *ngIf="isHidden" class="col-xs-5"> <pto-summary [selectedEmployee]="selectedEmployee"></pto-summary> </div> </div> 

my summary.component.ts

 import { Component, OnInit, Input } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { EmpInfoService } from './emp-info.service'; import { TrackerComponent } from './tracker.component'; import { EmpInfo } from './emp-info'; @Component({ selector: 'pto-summary', templateUrl: `./summary.component.html`, styleUrls: ['./summary.component.css'] }) export class SummaryComponent implements OnInit{ empInfo: EmpInfo[]; @Input() selectedEmployee: number; timeVar = " hours"; checkboxValue = false; constructor(private empInfoService: EmpInfoService) { } getEmpInfo(): void { this.empInfoService.getEmpInfos().then( empInfo => { this.empInfo = empInfo.sort((a, b) => a.LastName < b.LastName ? -1 : b.LastName < a.LastName ? 1 : 0); }); } ngOnInit(): void { this.getEmpInfo(); } changeTime(): void { if (!this.checkboxValue) { this.timeVar = " hours" this.empInfo[this.selectedEmployee].STDLTD = this.empInfo[this.selectedEmployee].STDLTD * 8; this.empInfo[this.selectedEmployee].Uncharged = this.empInfo[this.selectedEmployee].Uncharged * 8; this.empInfo[this.selectedEmployee].PTOBase = this.empInfo[this.selectedEmployee].PTOBase * 8; this.empInfo[this.selectedEmployee].PTOCarry = this.empInfo[this.selectedEmployee].PTOCarry * 8; this.empInfo[this.selectedEmployee].PTOBorrowed = this.empInfo[this.selectedEmployee].PTOBorrowed * 8; this.empInfo[this.selectedEmployee].PTOBalance = this.empInfo[this.selectedEmployee].PTOBalance * 8; this.empInfo[this.selectedEmployee].PTORequests = this.empInfo[this.selectedEmployee].PTORequests * 8; this.empInfo[this.selectedEmployee].PTORemaining = this.empInfo[this.selectedEmployee].PTORemaining * 8; this.empInfo[this.selectedEmployee].ETOEarned = this.empInfo[this.selectedEmployee].ETOEarned * 8; this.empInfo[this.selectedEmployee].ETORequests = this.empInfo[this.selectedEmployee].ETORequests * 8; this.empInfo[this.selectedEmployee].ETORemaining = this.empInfo[this.selectedEmployee].ETORemaining * 8; } else { this.timeVar = " days" this.empInfo[this.selectedEmployee].STDLTD = this.empInfo[this.selectedEmployee].STDLTD / 8; this.empInfo[this.selectedEmployee].Uncharged = this.empInfo[this.selectedEmployee].Uncharged / 8; this.empInfo[this.selectedEmployee].PTOBase = this.empInfo[this.selectedEmployee].PTOBase / 8; this.empInfo[this.selectedEmployee].PTOCarry = this.empInfo[this.selectedEmployee].PTOCarry / 8; this.empInfo[this.selectedEmployee].PTOBorrowed = this.empInfo[this.selectedEmployee].PTOBorrowed / 8; this.empInfo[this.selectedEmployee].PTOBalance = this.empInfo[this.selectedEmployee].PTOBalance / 8; this.empInfo[this.selectedEmployee].PTORequests = this.empInfo[this.selectedEmployee].PTORequests / 8; this.empInfo[this.selectedEmployee].PTORemaining = this.empInfo[this.selectedEmployee].PTORemaining / 8; this.empInfo[this.selectedEmployee].ETOEarned = this.empInfo[this.selectedEmployee].ETOEarned / 8; this.empInfo[this.selectedEmployee].ETORequests = this.empInfo[this.selectedEmployee].ETORequests / 8; this.empInfo[this.selectedEmployee].ETORemaining = this.empInfo[this.selectedEmployee].ETORemaining / 8; } } } 

and my summary.component.html

 <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title pull-left">{{empInfo[selectedEmployee].LastName | uppercase}} Summary</h3> <div style="float: right;"> <div class="onoffswitch"> <input [(ngModel)]="checkboxValue" (change)="changeTime()" type="checkbox" name="onoffswitch" class="onoffswitch-checkbox" id="myonoffswitch" checked> <label class="onoffswitch-label" for="myonoffswitch"> <span class="onoffswitch-inner"></span> <span class="onoffswitch-switch"></span> </label> </div> </div> <div class="clearfix"></div> </div> <div class="panel-body"> <form class="form-horizontal" role="form" style="overflow-x:auto;"> <fieldset> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-5"> Status </label> <div class="col-xs-7"> <select class="form-control" id="empStatus" [(ngModel)]="empInfo[selectedEmployee].EmpStat" name="empStatus"> <option value="Current">Current</option> <option value="Terminated">Terminated</option> </select> </div> </div> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-5"> Anniversary </label> <div class="col-xs-7"> <div class="input-group"> <input class='form-control' type="text" id="empAnniversary" [(ngModel)]="empInfo[selectedEmployee].Anniversary" name="empAnniversary" /> <span class="input-group-addon">years</span> </div> </div> </div> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-5"> Start Date </label> <div class="col-xs-7"> <input class='form-control' type="text" id="empStartDate" [ngModel]="empInfo[selectedEmployee].StartDate | date: 'MM/dd/y'" name="empStartDate"/> </div> </div> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-5"> Adjusted Start </label> <div class="col-xs-7"> <input class='form-control' type="text" id="empAdjustedStart" [ngModel]="empInfo[selectedEmployee].AdjustedStart | date: 'MM/dd/y'" name="empAdjustedStart"/> </div> </div> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-5"> STD/LTD </label> <div class="col-xs-7"> <div class="input-group"> <input class='form-control' type="text" id="empSTDLTD" [(ngModel)]="empInfo[selectedEmployee].STDLTD" name="empSTDLTD" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> </div> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-5"> Uncharged </label> <div class="col-xs-7"> <div class="input-group"> <input class='form-control' type="text" id="empUncharged" [(ngModel)]="empInfo[selectedEmployee].Uncharged" name="empUncharged" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> </div> </div> </fieldset> <fieldset> <h4>PTO</h4> <br /> <div class="col-xs-12"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <div class="col-xs-1"></div> <label class="col-xs-2"> Base </label> <div class="col-xs-3"> <div class="input-group"> <input class='form-control' type="text" id="ptoBase" [(ngModel)]="empInfo[selectedEmployee].PTOBase" name="ptoBase" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> <div class="col-xs-6"> </div> </div> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-2" style="font-weight: bold;"> &#43; </label> <label class="col-xs-4"> Carryover </label> <div class="col-xs-6"> <div class="input-group"> <input class='form-control' type="text" id="ptoCarry" [(ngModel)]="empInfo[selectedEmployee].PTOCarry" name="ptoCarry" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> </div> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <div class="col-xs-1"></div> <label class="col-xs-4"> Balance </label> <div class="col-xs-6"> <div class="input-group"> <input class='form-control' type="text" id="ptoBalance" [(ngModel)]="empInfo[selectedEmployee].PTOBalance" name="ptoBalance" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> <div class="col-xs-1"></div> </div> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-2" style="font-weight: bold;"> &#8213; </label> <label class="col-xs-4"> Borrowed </label> <div class="col-xs-6"> <div class="input-group"> <input class='form-control' type="text" id="ptoBorrowed" [(ngModel)]="empInfo[selectedEmployee].PTOBorrowed" name="ptoBorrowed" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> </div> <hr style="border: solid 1px black;border-bottom:1px solid black;clear:both" /> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-1" style="font-weight: bold;"> &#8213; </label> <label class="col-xs-4"> Requests </label> <div class="col-xs-6"> <div class="input-group"> <input class='form-control' type="text" id="ptoRequests" [(ngModel)]="empInfo[selectedEmployee].PTORequests" name="ptoRequests" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> <div class="col-xs-1"></div> </div> <hr style="border: solid 1px black;border-bottom:1px solid black;clear:both" /> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-2" style="font-weight: bold;"> &#61; </label> <label class="col-xs-4"> Balance </label> <div class="col-xs-6"> <div class="input-group"> <input class='form-control' type="text" id="ptoBalance" [(ngModel)]="empInfo[selectedEmployee].PTOBalance" name="ptoBalance" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> </div> </div> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-1" style="font-weight: bold;"> &#61; </label> <label class="col-xs-4"> Available </label> <div class="col-xs-6"> <div class="input-group"> <input class='form-control' type="text" id="ptoRemaining" [(ngModel)]="empInfo[selectedEmployee].PTORemaining" name="ptoRemaining" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> <div class="col-xs-1"></div> </div> </div> </fieldset> <fieldset> <h4>ETO</h4> <br /> <div class="col-xs-6"> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <div class="col-xs-2"></div> <label class="col-xs-4"> Earned </label> <div class="col-xs-6"> <div class="input-group"> <input class='form-control' type="text" id="etoEarned" [(ngModel)]="empInfo[selectedEmployee].ETOEarned" name="etoEarned" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> </div> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-2"> &#8213; </label> <label class="col-xs-4"> Requests </label> <div class="col-xs-6"> <div class="input-group"> <input class='form-control' type="text" id="etoRequests" [(ngModel)]="empInfo[selectedEmployee].ETORequests" name="etoRequests" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> </div> <hr style="border: solid 1px black;border-bottom:1px solid black;clear:both" /> <div class="form-group" *ngIf="empInfo && empInfo.length > selectedEmployee"> <label class="col-xs-2"> &#61; </label> <label class="col-xs-4"> Available </label> <div class="col-xs-6"> <div class="input-group"> <input class='form-control' type="text" id="etoRemaining" [(ngModel)]="empInfo[selectedEmployee].ETORemaining" name="etoRemaining" /> <span class="input-group-addon">{{timeVar}}</span> </div> </div> </div> </div> <div class="col-xs-6"></div> </fieldset> </form> </div> </div> 

I assume based on the message that the problem is here: {{empInfo[selectedEmployee].LastName | uppercase}} {{empInfo[selectedEmployee].LastName | uppercase}}

If your service is using Http, then it is an asynchronous operation. That means that your page is trying to display before the data is available.

There are several common ways to resolve this issue, but your best bet may be to add an *ngIf in your HTML to check whether you have data before displaying the page.

Something like you already did here:

*ngIf="empInfo && empInfo.length

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM