Angular:加载组件时,数据未定义

时间:2018-06-18 17:31:05

标签: html json angular typescript angular6

我毫不犹豫地问这个问题,因为我知道答案是非常明显的,让我盯着我看,但经过2天与代码的斗争后,我还要把头发拉出来。

我是棱角分明的新手(仅限FYI),但并不熟悉它背后的概念。我已经构建了一个小应用程序,它试图从托管在另一个服务器(可能)上的API读取数据,该服务器向我发回一个json对象。然后,此对象将填充组件。这是一些示例代码:

页面服务

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';

import { Observable } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';

import { HttpErrorHandler, HandleError } from './http-error-handler.service';
import { AlcalaPage } from '../../shared/models/alcala-page.model';
import { environment } from '../../../environments/environment';

const httpOptions = {
  headers: new HttpHeaders( {
    'Content-Type':  'application/json'
  })
};

@Injectable()
export class PageService {
  pageServiceUrl: string;
  private handleError: HandleError

  constructor(private http: HttpClient, private httpErrorHandler: HttpErrorHandler) {
    this.pageServiceUrl = environment.apiUrl + 'page/';
    this.handleError = httpErrorHandler.createHandleError('PageService');
  }

  getPage(pageid: string): Observable<AlcalaPage> {
    return this.http.get<AlcalaPage>(this.pageServiceUrl + pageid)
      .pipe(
          tap(data => console.log('Data is ' + data.months[0].expenses[0].entryType)),
          catchError(this.handleError('getPage', null))
        );
  }
}

page.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { environment } from '../../../environments/environment';

import { AlcalaPage } from '../../shared/models/alcala-page.model';
import { PageService } from '../service/page.service';

@Component({
  selector: 'app-page',
  templateUrl: './page.component.html',
  styleUrls: ['./page.component.scss']
})
export class PageComponent implements OnInit {
  pageid: string;
  imageurl: string;
  dataModel: AlcalaPage;
  public apiData;
  constructor(private route: ActivatedRoute, private pageService: PageService) {
  }

  ngOnInit() {
    this.route.params.subscribe(params => {
      this.pageid = params['id'];
    });
    this.getPage();
    this.imageurl = environment.imageUrl + this.pageid + '.jpg';
  }

  getPage(): void {
    this.pageService.getPage(this.pageid)
      .subscribe(
        data => { this.dataModel = data; },
        err => console.error(err),
        () => console.log('page data loaded.')
        );
  }
}

page.component.html

<div class="container" fxLayout="row" fxLayout.xs="column" fxLayoutGap="0.5%" fxLayoutAlign="left">
  <div fxFlex="70%">
    <h2 class="right-align">{{dataModel.year}}</h2>
    <mat-tab-group>
      <mat-tab label="English">
        <div *ngFor="let month of dataModel.months">
          <app-month [dataModel]="month" currentLang="en"></app-month>
        </div>
      </mat-tab>
      <mat-tab label="Spanish">
        <div *ngFor="let month of dataModel.months">
          <app-month [dataModel]="month" currentLang="es"></app-month>
        </div>
      </mat-tab>
    </mat-tab-group>
  </div>
  <div fxFlex="20%">
    <ngx-imageviewer [src]="this.imageurl"></ngx-imageviewer>
  </div>
</div>

问题似乎源于页面的生命周期以及我(明显)对生命周期如何变化的误解。截至目前,页面上的年份字段正在加载(<h2 class="right-align">{{dataModel.year}}</h2>),标签组正在显示它的标题(因此我看到&#34的标签;英语&#34;以及标签for&#34; Spanish&#34;但没有其他东西正在加载。当我检查控制台时,我看到一条错误消息,指出状态无法读取属性&#34;月份&#34;未定义。我发现这个错误消息令人困惑的两个原因:

  1. dataModel(其中月份是其成员)显然未定义,因为我能够在标记中呈现dataModel.year。
  2. dataModel.months肯定有数据,因为当服务从服务器加载数据时,我能够向控制台写出各种值(我玩了将json对象的许多不同属性记录到控制台)所以我可以确保我的所有数据都存在。)
  3. 我的猜测是a)我在标签中的* ngFor循环中做错了什么或b)我在页面生命周期中遗漏了一些东西。但是我不知道我可能做错了什么,因为我所遵循和看过的所有教程似乎都按照我实施的方式做事。任何对我可能做错的事情有任何想法的人都将不胜感激。

1 个答案:

答案 0 :(得分:0)

它已加载异步,因此最初它将是未定义的。

请尝试执行let month of dataModel?.month,只有在设置month时才会显示dataModelhttps://angular.io/guide/template-syntax#the-safe-navigation-operator----and-null-property-paths