programing

각도 2:컴포넌트를 렌더링하기 전에 데이터를 로드하는 방법

golfzon 2023. 3. 5. 10:51
반응형

각도 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);
}

갱신하다

원래의

언제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

반응형