我的EventRegister组件:
import {Component,OnInit,ElementRef} from "angular2/core"; import {ApiService} from "../../services/api.service"; import {EventModel} from '../../models/EventModel'; import {Router,ROUTER_DIRECTIVES,ROUTER_PROVIDERS,RouteConfig,RouteParams,RouterLink} from 'angular2/router'; import {FORM_PROVIDERS,FORM_DIRECTIVES,Control} from 'angular2/common'; @Component({ selector: "register",templateUrl: "/events/register" // provider array is added in parent component }) export class EventRegister implements OnInit { eventId: string; ev: EventModel; constructor(private _apiService: ApiService,params: RouteParams) { this.eventId = params.get('id'); } fetchEvent(): void { this._apiService.get.event(this.eventId).then(event => { this.ev = event; console.log(event); // Has a value console.log(this.ev); // Has a value }); } ngOnInit() { this.fetchEvent(); console.log(this.ev); // Has NO value } }
我的EventRegister模板
<register> Hi this sentence is always visible,even if `ev property` is not loaded yet <div *ngIf="ev"> I should be visible as soon the `ev property` is loaded. Currently I am never shown. <span>{{event.id }}</span> </div> </register>
我的API服务
import "rxjs/Rx" import {Http} from "angular2/http"; import {Injectable} from "angular2/core"; import {EventModel} from '../models/EventModel'; @Injectable() export class ApiService { constructor(private http: Http) { } get = { event: (eventId: string): Promise<EventModel> => { return this.http.get("api/events/" + eventId).map(response => { return response.json(); // Has a value }).toPromise(); } } }
在ngOnInit函数中的API调用完成之前,该组件被渲染。所以我从来没有看到我的视图模板中的事件ID。所以看起来这是一个ASYNC问题。我希望ev(EventRegister组件)在设置ev属性后进行一些工作。遗憾的是,当属性设置时,它不会显示标有* ngIf =“ev”的div。
问题:我使用好的方法吗?如果不;在组件开始呈现之前加载数据的最佳方式是什么?
注意:在此angular2 tutorial中使用ngOnInit方法。
编辑:
两种可能的解决方案。首先是撷取fetchEvent,并在ngOnInit函数中使用API服务。
ngOnInit() { this._apiService.get.event(this.eventId).then(event => this.ev = event); }
第二个解决方案就像给出的答案。
fetchEvent(): Promise<EventModel> { return this._apiService.get.event(this.eventId); } ngOnInit() { this.fetchEvent().then(event => this.ev = event); }
>如果使用路由器,您可以使用生命周期挂钩或解析器来延迟导航,直到数据到达。
https://angular.io/docs/ts/latest/guide/router.html#!#guards
>在根组件初始化之前加载数据APP_INITIALIZER可以使用How to pass parameters rendered from backend to angular2 bootstrap method
原版的
当console.log(this.ev)在this.fetchEvent()之后执行时;这并不意味着fetchEvent()调用已经完成,这只意味着它被调度。当console.log(this.ev)被执行时,对服务器的调用甚至没有进行,当然还没有返回值。
更改fetchEvent()以返回Promise
fetchEvent(): void { return this._apiService.get.event(this.eventId).then(event => { this.ev = event; console.log(event); // Has a value console.log(this.ev); // Has a value }); }
更改ngOnInit()等待Promise完成
ngOnInit() { this.fetchEvent().then(() => console.log(this.ev)); // Now has value; }
这实际上不会为你的用例买多。
我的建议:将整个模板包含在< div * ngIf =“isDataAvailable”> (模板内容)< / div>
和ngOnInit()
isDataAvailable:boolean = false; ngOnInit() { this.fetchEvent().then(() => this.isDataAvailable = true); // Now has value; }