【发布时间】:2018-11-27 14:36:48
【问题描述】:
我犹豫要不要问这个问题,因为我知道答案将是非常明显的事情,正盯着我的脸,但是在与代码斗争 2 天后,我快要拔掉头发了。
我是 Angular 的新手(仅供参考),但对它背后的概念并不陌生。我构建了一个小型应用程序,它试图从托管在另一台服务器上的 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>)并且选项卡组正在显示它的标题(所以我看到一个“英语”选项卡和一个“西班牙语”选项卡,但没有其他内容正在加载。当我检查控制台,我看到一条错误消息,指出无法读取未定义的属性“月”。我发现此错误消息令人困惑,原因有两个:
- dataModel(其中月份是成员)显然不是未定义的,因为我能够在标签中呈现 dataModel.year。
- dataModel.months 肯定有数据,因为当服务从服务器加载数据时,我能够将各种值写入控制台(我尝试将 json 对象的许多不同属性记录到控制台所以我可以确保我的所有数据都存在)。
我的猜测是,要么 a) 我在标签中的 *ngFor 循环中做错了什么,要么 b) 我在页面生命周期中遗漏了一些东西。但是我不知道我可能做错了什么,因为我遵循并查看的所有教程似乎都按照我实现的方式做事。任何对我可能做错的事情有任何想法的人将不胜感激。
【问题讨论】:
-
它是异步加载的,所以最初它是未定义的。尝试改用
let month of dataModel?.month,它只会读取monthisdataModelhas been set: angular.io/guide/… -
谢谢!这解决了我的问题。如果您可以将此作为答案发布,我会接受。
-
没有问题,我已将其发布为答案。谢谢
标签: html json angular typescript angular6