【问题标题】:Angular cannot find property of undefinedAngular 找不到未定义的属性
【发布时间】:2021-03-11 23:59:13
【问题描述】:

我对 Angular 比较陌生,并且在使用服务返回单个值时遇到了麻烦。以下是相关代码:

该组件应该从存储在 .json 文件中的特定团队检索数据,该文件包含多个团队的数据。

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { StandingsService } from '../standings/standings.service';
import { IStanding } from '../standings/standing';

@Component({
  selector: 'ur-teams',
  templateUrl: './teams.component.html',
  styleUrls: ['./teams.component.css']
})
export class TeamsComponent implements OnInit {
  teamName; currAge; currDiv; 
  currTeam: IStanding;
  errorMessage: '';

  constructor(private route: ActivatedRoute,
    private router: Router,
    private standingService: StandingsService) {
  }
  ngOnInit() {
    this.teamName = this.route.snapshot.paramMap.get('team').toLowerCase();
    this.currAge = this.route.snapshot.paramMap.get('age').toLowerCase();
    this.currDiv = this.route.snapshot.paramMap.get('division').toLowerCase();
    this.getTeam(this.currAge, this.currDiv, this.teamName);
  }
  getTeam(age: string, gender: string, teamName: string): void {
    this.standingService.getTeam(age, gender, teamName).subscribe({
      next: team => this.currTeam = team,
      error: err => this.errorMessage = err
    });
  }

这是从 .json 文件中获取数据的服务:

import { Injectable } from '@angular/core';
import { IStanding } from './standing';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';

@Injectable({
    providedIn: 'root'
})
export class StandingsService {
    private standingsUrl = 'api/standings/';
    private newUrl;
    allTeams;
    team;
    team_pipe;
    constructor(private http: HttpClient){}

    getStandings(ageDivison: string, gendDivision: string): Observable<IStanding[]> {
        this.newUrl = this.standingsUrl + ageDivison + '/' + gendDivision + '.json';
        return this.http.get<IStanding[]>(this.newUrl).
            pipe(
                tap(data => console.log('All: ' + JSON.stringify(data))),
                catchError(this.handleError)
            ); 
    }
    getTeam(age: string, gender: string, teamName: string): Observable<IStanding | undefined>{
        return this.getStandings(age, gender)
            .pipe(
                map((standings: IStanding[]) => standings.find(
                    t => t.teamName.toLowerCase() === teamName.toLowerCase()))
            );
    }
    private handleError(err: HttpErrorResponse){
        let errorMessage = '';
        if (err.error instanceof ErrorEvent) {
          errorMessage = `An error occurred: ${err.error.message}`;
        } else {
          errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`
        }
        console.error(errorMessage);
        return throwError(errorMessage);
    }
}

这是与团队组件相关的 HTML:

<table class="table table-bordered table-striped table-hover">
    <thead class="thead">
        <tr><th class="text-center" id="borderless-cell" colspan="4">{{teamName}}</th></tr>
    </thead>
    <thead class="thead-dark">
        <tr>
            <th mat-sort-header="rank">Rank</th>
            <th mat-sort-header="teamName">Team</th>
            <th mat-sort-header="powerRanking">PR</th>
            <th mat-sort-header="region">Region</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>FIX</td>
            <td><a routerLinkActive='active' [routerLink]="['/teams']">{{currTeam.teamName}}</a></td>
            <td>{{currTeam.powerRanking}}</td>
            <td>{{currTeam.region}}</td>
        </tr>
    </tbody>
</table>
<table class="table table-bordered table-striped table-hover">
    <thead class="thead">
        <tr><th class="text-center" id="borderless-cell" colspan="5">Current Season Tournaments</th></tr>
    </thead>
    <thead class="thead-dark">
        <tr>
            <th mat-sort-header="rank">Seed</th>
            <th mat-sort-header="teamName">Finish</th>
            <th mat-sort-header="powerRanking">W</th>
            <th mat-sort-header="region">L</th>
            <th mat-sort-header="region">+/-</th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor='let tournament of currTeam.tournaments'>
            <td>FIX</td>
            <td><a routerLinkActive='active' [routerLink]="['/teams']">{{currTeam.teamName}}</a></td>
            <td>{{currTeam.powerRanking}}</td>
            <td>{{currTeam.region}}</td>
        </tr>
    </tbody>
</table>

第一个表实际上打印了 currTeam.teamName、currTeam.powerRanking 和 currTeam.region,但如果我尝试在团队组件中使用 console.log(this.currTeam),它会返回“未定义”。在加载团队组件页面时,我还会收到一条错误日志:

错误类型错误:无法读取未定义的属性“teamName” 在 TeamsComponent_Template (teams.component.html:16)

最后,应该填充锦标赛信息的第二张桌子是空的。作为参考,这是单个团队在 json 文件中的样子:

{
        "teamName" : "Sockeye",
        "powerRanking": 1000,
        "region": "OV",
        "tournaments":{
            "US Open": {
                "Seed": 1,
                "Finish": 3,
                "Wins": 5,
                "Losses": 2,
                "+/-": 23
            },
            "Select Flight Invite": {
                "Seed": 5,
                "Finish": 2,
                "Wins": 6,
                "Losses": 1,
                "+/-": 8
            },
            "Three Ring Rally": {
                "Seed": 1,
                "Finish": 1,
                "Wins": 7,
                "Losses": 0,
                "+/-": 37
            }
        }
    }

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    好吧,我知道我做错了什么——这是一些事情。

    首先,我需要添加一个&lt;div *ngIf='currTeam'&gt; 来包裹整个teams.component.html。这解决了我在加载团队组件时看到的所有错误。

    第二个问题是由于我的 .json 文件格式。我所要做的就是将tournaments 部分设为数组而不是嵌套字典。现在看起来像:

    "tournaments":[
                {
                    "name": "US Open",
                    "seed": 1,
                    "finish": 3,
                    "wins": 5,
                    "losses": 2,
                    "plus_minus": 23
                },
                {
                    "name": "Select Flight Invite",
                    "seed": 5,
                    "finish": 2,
                    "wins": 6,
                    "losses": 1,
                    "plus_minus": 8
                },
                {
                    "name": "US Open",
                    "seed": 1,
                    "finish": 1,
                    "wins": 7,
                    "losses": 0,
                    "plus_minus": 37
                }
            ]

    这样就成功了!

    【讨论】:

    • 更好的解决方案是将 ng-content 作为 *ngIf 的元素,因为这样不会用不必要的元素污染 Dom。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 2020-07-09
    • 2018-11-26
    相关资源
    最近更新 更多