Angular - 无法读取属性'..'未定义

问题描述:

在我的Angular项目中,我收到一个错误,说“无法读取属性'...'未定义的”,其中'...'是索引无论从组合框中选择哪一个员工。Angular - 无法读取属性'..'未定义

我的项目的一点背景。我让用户从组合框(tracker.component)中选择一个员工。然后,该雇员的索引被采用并用于显示该雇员的信息(summary.component)。它的效果很好,并且有下一个,上一个,第一个,最后一个按钮,但是每当我打开摘要面板(summary.component)时,就会得到上面在浏览器中提到的错误。我在哪里搞乱?

这里是我的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; 
 
    } 
 
}

我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>

我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; 
 
     } 
 
    } 
 
}

和我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>

+0

我基础上,问题是这里的消息假设:{{empInfo [selectedEmployee] .LastName |大写}}我不确定你可以使用数组索引的安全导航操作。 – DeborahK

+0

@DeborahK是的,我检查,它说这是它有一个问题的线 – asdf

我认为基于消息,问题就在这里:{{empInfo[selectedEmployee].LastName | uppercase}}

如果你的服务使用Http,那么它是一个异步操作。这意味着您的网页正在尝试在之前显示数据可用。

有几种常见的方法可以解决这个问题,但最好的办法可能是在HTML中添加一个* ngIf来检查显示页面之前是否有数据。

喜欢的东西,你已经在这里做:

*ngIf="empInfo && empInfo.length 
+0

啊好吧,我刚刚错过了那一个。谢谢! – asdf