Angular: 加载组件时,数据给我 undefined
Angular: When loading a component, the data is giving me undefined
我犹豫要不要问这个问题,因为我知道答案将是非常明显的,而且直面我的面孔,但是在与代码抗争了 2 天之后,我快要拔头发了。
我是 angular 的新手(仅供参考),但对它背后的概念并不陌生。我构建了一个小型应用程序,它试图从另一台服务器上托管的 API 读取数据(可能),这会向我发送回 json object。然后 object 填充组件。这是一些示例代码:
页面服务
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>
),选项卡组显示为 header(所以我看到 "English" 的选项卡和 "Spanish" 但没有其他内容正在加载。当我检查控制台时,我看到一条错误消息,指出无法读取未定义的 属性 "months"。我发现此错误消息令人困惑有两个原因:
- dataModel(其中 months 是成员)显然不是未定义的,因为我能够在标签中呈现 dataModel.year。
- dataModel.months 中肯定有数据,因为当服务从服务器加载数据时,我能够将各种值写到控制台(我尝试记录 json object 到控制台,这样我就可以确保我的所有数据都存在)。
我的猜测是 a) 我在标签的 *ngFor 循环中做错了什么或者 b) 我在页面生命周期中遗漏了一些东西。但我不知道我可能做错了什么,因为我遵循和查看的所有教程似乎都按照我实施的方式做事。任何对我可能做错的事情有任何想法的人将不胜感激。
它是异步加载的,所以最初它是未定义的。
尝试做 let month of dataModel?.month
,如果设置了 dataModel
,它只会读取 month
:https://angular.io/guide/template-syntax#the-safe-navigation-operator----and-null-property-paths
我犹豫要不要问这个问题,因为我知道答案将是非常明显的,而且直面我的面孔,但是在与代码抗争了 2 天之后,我快要拔头发了。
我是 angular 的新手(仅供参考),但对它背后的概念并不陌生。我构建了一个小型应用程序,它试图从另一台服务器上托管的 API 读取数据(可能),这会向我发送回 json object。然后 object 填充组件。这是一些示例代码:
页面服务
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>
),选项卡组显示为 header(所以我看到 "English" 的选项卡和 "Spanish" 但没有其他内容正在加载。当我检查控制台时,我看到一条错误消息,指出无法读取未定义的 属性 "months"。我发现此错误消息令人困惑有两个原因:
- dataModel(其中 months 是成员)显然不是未定义的,因为我能够在标签中呈现 dataModel.year。
- dataModel.months 中肯定有数据,因为当服务从服务器加载数据时,我能够将各种值写到控制台(我尝试记录 json object 到控制台,这样我就可以确保我的所有数据都存在)。
我的猜测是 a) 我在标签的 *ngFor 循环中做错了什么或者 b) 我在页面生命周期中遗漏了一些东西。但我不知道我可能做错了什么,因为我遵循和查看的所有教程似乎都按照我实施的方式做事。任何对我可能做错的事情有任何想法的人将不胜感激。
它是异步加载的,所以最初它是未定义的。
尝试做 let month of dataModel?.month
,如果设置了 dataModel
,它只会读取 month
:https://angular.io/guide/template-syntax#the-safe-navigation-operator----and-null-property-paths