HiveBrain v1.2.0
Get Started
← Back to all entries
snippettypescriptangularCritical

Angular2: How to load data before rendering the component?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
datahowloadcomponentangular2thebeforerendering

Problem

I am trying to load an event from my API before the component gets rendered. Currently I am using my API service which I call from the ngOnInit function of the component.

My EventRegister component:

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
    }
}


My EventRegister template


Hi this sentence is always visible, even if
ev property is not loaded yet

I should be visible as soon the
ev property is loaded. Currently I am never shown.
{{event.id }}




My API service

```
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 => {
return this.http.get("api/events/" + eventId).map(response => {
return response.json(); // Has a value
}).toPromise();
}
}

Solution

update

-
If you use the router you can use lifecycle hooks or resolvers to delay navigation until the data arrived.
https://angular.io/guide/router#milestone-5-route-guards

-
To load data before the initial rendering of the root component APP_INITIALIZER can be used How to pass parameters rendered from backend to angular2 bootstrap method

original

When console.log(this.ev) is executed after this.fetchEvent();, this doesn't mean the fetchEvent() call is done, this only means that it is scheduled. When console.log(this.ev) is executed, the call to the server is not even made and of course has not yet returned a value.

Change fetchEvent() to return a 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
});
}


change ngOnInit() to wait for the Promise to complete
ngOnInit() {
this.fetchEvent().then(() =>
console.log(this.ev)); // Now has value;
}


This actually won't buy you much for your use case.

My suggestion: Wrap your entire template in an (template content)

and in ngOnInit()
isDataAvailable:boolean = false;

ngOnInit() {
this.fetchEvent().then(() =>
this.isDataAvailable = true); // Now has value;
}

Context

Stack Overflow Q#35655361, score: 158

Revisions (0)

No revisions yet.