각도 2:컴포넌트를 렌더링하기 전에 데이터를 로드하는 방법
컴포넌트가 렌더링되기 전에 API에서 이벤트를 로드하려고 합니다.현재 컴포넌트의 ngOnInit 함수에서 호출하는 API 서비스를 사용하고 있습니다.
나의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>
My 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();
}
}
}
컴포넌트는 API 호출 전에 렌더링됩니다.ngOnInit데이터 가져오기가 완료되었습니다.뷰 템플릿에서 이벤트 ID를 볼 수 없습니다.이것은 비동기 문제인 것 같습니다.의 바인딩을 예상했습니다.ev(EventRegister컴포넌트)를 사용하여 다음 작업을 수행합니다.ev속성이 설정되었습니다.슬프게도, 그것은 그것을 보여주지 않는다.div로 표시된.*ngIf="ev"속성을 설정할 때 사용합니다.
질문:제가 좋은 방법을 사용하고 있나요?그렇지 않은 경우: 컴포넌트의 렌더링을 시작하기 전에 데이터를 로드하는 가장 좋은 방법은 무엇입니까?
주의:ngOnInitaccess는 이 angular2 튜토리얼에서 사용됩니다.
편집:
두 가지 해결책이 있습니다.첫 번째는 이 모든 것을 버리는 것이었다.fetchEventAPI 서비스를 사용하면 됩니다.ngOnInit기능.
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/guide/router#milestone-5-route-guards
루트 구성 요소를 처음 렌더링하기 전에 데이터를 로드하려면 다음과 같이 하십시오.
APP_INITIALIZER사용할 수 있습니다 백엔드에서 angular2 부트스트랩 메서드로 렌더링된 파라미터를 전달하는 방법
원래의
언제console.log(this.ev)다음 후에 실행됩니다.this.fetchEvent();즉, 이것은,fetchEvent()콜이 완료됩니다.이것은 스케줄 되어 있는 것을 의미할 뿐입니다.언제console.log(this.ev)서버에 대한 콜도 이루어지지 않고 물론 아직 값을 반환하지 않았습니다.
바꾸다fetchEvent()반환하다Promise
fetchEvent(){
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"> (template content) </div>
및 인ngOnInit()
isDataAvailable:boolean = false;
ngOnInit() {
this.fetchEvent().then(() =>
this.isDataAvailable = true); // Now has value;
}
Angular2+에서 Resolvers를 사용하여 데이터를 프리페치할 수 있습니다. Resolvers는 컴포넌트가 완전히 로드되기 전에 데이터를 처리합니다.
예를 들어 이미 로그인한 사람이 Dashboard(대시보드)로 이동하는 등 특정 상황이 발생한 경우에만 구성 요소를 로드하려는 경우가 많습니다. 이 경우 해결 프로그램이 매우 편리합니다.
리졸버를 사용하여 데이터를 컴포넌트로 전송할 수 있는 방법 중 하나를 위해 작성한 간단한 다이어그램을 참조하십시오.
리졸버를 코드에 적용하는 것은 매우 간단합니다.리졸버를 작성하는 방법을 알기 위해 스니펫을 작성했습니다.
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;
}
});
}
}
및 모듈:
import { MyResolver } from './my-resolver.service';
@NgModule({
imports: [
RouterModule.forChild(myRoutes)
],
exports: [
RouterModule
],
providers: [
MyResolver
]
})
export class MyModule { }
컴포넌트에서 다음과 같이 액세스 할 수 있습니다.
/////
ngOnInit() {
this.route.data
.subscribe((data: { mydata: myData }) => {
this.id = data.mydata.id;
});
}
/////
Route에서는 (통상 app.routing.ts 파일에서) 다음과 같이 처리됩니다.
////
{path: 'yourpath/:id', component: YourComponent, resolve: { myData: MyResolver}}
////
UI에서 다음과 같은 작업을 수행할 수 있는 좋은 솔루션이 있습니다.
<div *ngIf="isDataLoaded">
...Your page...
</div
isDataLoaded가 true인 경우에만 페이지가 렌더링됩니다.
언급URL : https://stackoverflow.com/questions/35655361/angular2-how-to-load-data-before-rendering-the-component
'programing' 카테고리의 다른 글
| JSON 파일 정규화 (0) | 2023.03.05 |
|---|---|
| AngularJS에서 CSS 스타일을 조건부로 적용하는 방법은 무엇입니까? (0) | 2023.03.05 |
| JSON과 BSON의 비교 (0) | 2023.03.05 |
| 각진 쿠키는 왜 주입할 수 없는 거죠? (0) | 2023.03.05 |
| Oracle SQL Developer에서 tnsnames.ora 사용 (0) | 2023.03.05 |
