Typescript Angular2:如何在渲染组件之前加载数据?
我试图在呈现组件之前从API加载事件。目前我正在使用我的API服务,我从组件的ngOnInit函数调用该服务 我的Typescript Angular2:如何在渲染组件之前加载数据?,typescript,angular,angular2-services,angular2-http,Typescript,Angular,Angular2 Services,Angular2 Http,我试图在呈现组件之前从API加载事件。目前我正在使用我的API服务,我从组件的ngOnInit函数调用该服务 我的EventRegister组件: import {Component, OnInit, ElementRef} from "angular2/core"; import {ApiService} from "../../services/api.service"; import {EventModel} from '../../models/EventModel'; import {
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
模板
嗨,这句话始终可见,即使尚未加载'ev property'
“ev属性”一加载,我就可以看到了。目前,我从未出现过。
{{event.id}
我的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();
}
}
}
第二个解决方案。我喜欢给出的答案
fetchEvent(): Promise<EventModel> {
return this._apiService.get.event(this.eventId);
}
ngOnInit() {
this.fetchEvent().then(event => this.ev = event);
}
fetchEvent():承诺{
返回此.apiService.get.event(this.eventId);
}
恩戈尼尼特(){
this.fetchEvent().then(event=>this.ev=event);
}
更新
- 如果使用路由器,则可以使用生命周期挂钩或解析器延迟导航,直到数据到达。
- 要在根组件的初始呈现之前加载数据,可以使用
APP\u初始值设定项
this.fetchEvent()之后执行console.log(this.ev)
时
,这并不意味着fetchEvent()
调用已完成,这只意味着它已被调度。当执行console.log(this.ev)
时,甚至没有调用服务器,当然也没有返回值
更改fetchEvent()
以返回Promise
fetchEvent(){
返回此.apiService.get.event(this.eventId)。然后(event=>{
this.ev=事件;
console.log(event);//有一个值
console.log(this.ev);//有一个值
});
}
更改ngOnInit()
以等待承诺完成
ngOnInit(){
this.fetchEvent()。然后(()=>
console.log(this.ev));//现在有值;
}
这实际上不会为您的用例买很多东西
我的建议是:将整个模板包装在(模板内容)
在ngOnInit()中
isDataAvailable:boolean=false;
恩戈尼尼特(){
this.fetchEvent()。然后(()=>
this.isDataAvailable=true);//现在有值;
}
您可以在Angular2+中使用解析程序预取数据,解析程序在组件完全加载之前处理数据
在许多情况下,您希望仅在发生某些事情时加载组件,例如,仅当用户已登录时才导航到仪表板,在这种情况下,解析程序非常方便
请看我为您创建的简单图表,了解如何使用解析器将数据发送到组件
将解析器应用于您的代码非常简单,我创建了代码片段,让您了解如何创建解析器:
import { Injectable } from '@angular/core';
import { Router, Resolve, RouterStateSnapshot, ActivatedRouteSnapshot } from '@angular/router';
import { MyData, MyService } from './my.service';
@Injectable()
export class MyResolver implements Resolve<MyData> {
constructor(private ms: MyService, private router: Router) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<MyData> {
let id = route.params['id'];
return this.ms.getId(id).then(data => {
if (data) {
return data;
} else {
this.router.navigate(['/login']);
return;
}
});
}
}
您可以在组件中访问它,如下所示:
/////
ngOnInit() {
this.route.data
.subscribe((data: { mydata: myData }) => {
this.id = data.mydata.id;
});
}
/////
在路由中(通常在app.routing.ts文件中)类似的内容:
我发现一个很好的解决方案是在UI上执行以下操作:
<div *ngIf="isDataLoaded">
...Your page...
</div
…你的页面。。。
事实上,你的第一条评论效果很好。我只删除了整个fetchEvent
函数,将apiService.get.event
函数放在ngOnInit
中,它按照我的意图工作。谢谢我也会尽快接受你们的答案。出于某种原因,我在Angular 1.x上使用了这种方法。嗯,这应该被看作是一种黑客行为,而不是一个合适的解决方案。我们应该在角5上做得更好。你到底不喜欢什么?我认为这两种方法都很好。我认为这个解决方案只适用于Angular 1,而不是Angular>=2,因为Angular的单向数据流规则禁止在合成视图后对其进行更新。这两个钩子都在组件的视图合成后触发。div根本不进行渲染。我们不想阻止它渲染,我们想延迟它。它不起作用的原因是angular2中没有双向绑定@phil你能解释一下它是如何为你工作的吗?好的,我正在使用ChangeDetectionStrategy.Push
,将其更改为ChangeDetectionStrategy.Default
使其与模板双向绑定。6。有效。我想你错过了Routes
数组下的路由配置条目(通常在app.routing.ts文件中):{path:'yourpath/:id',component:YourComponent,resolve:{myData:myData}}
@Voicu,它不应该涵盖所有部分,但我同意,它使答案更全面,所以我添加了。。。感谢您纠正最后一部分,路由中的resolve参数需要指向解析器本身,而不是数据类型,即resolve:{myData:MyResolver}
myData是在MyService中定义的模型对象吗?此解决方案适用于在页面加载之前获取数据,但不适用于检查记录的用户或用户角色。为此,您应该使用GuardAuth gaurds也可以这样做为什么您使用Http而不是HttpClient?如果使用HttpClient,就不必像自动转换json那样将响应转换为json。
/////
ngOnInit() {
this.route.data
.subscribe((data: { mydata: myData }) => {
this.id = data.mydata.id;
});
}
/////
////
{path: 'yourpath/:id', component: YourComponent, resolve: { myData: MyResolver}}
////
<div *ngIf="isDataLoaded">
...Your page...
</div