Angular2: How to load data before rendering the component? Angular2: How to load data before rendering the component? angular angular

Angular2: How to load data before rendering the component?


update

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 <div *ngIf="isDataAvailable"> (template content) </div>

and in ngOnInit()

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


A nice solution that I've found is to do on UI something like:

<div *ngIf="isDataLoaded"> ...Your page...</div

Only when: isDataLoaded is true the page is rendered.


You can pre-fetch your data by using Resolvers in Angular2+, Resolvers process your data before your Component fully be loaded.

There are many cases that you want to load your component only if there is certain thing happening, for example navigate to Dashboard only if the person already logged in, in this case Resolvers are so handy.

Look at the simple diagram I created for you for one of the way you can use the resolver to send the data to your component.

enter image description here

Applying Resolver to your code is pretty simple, I created the snippets for you to see how the Resolver can be created:

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

and in the module:

import { MyResolver } from './my-resolver.service';@NgModule({  imports: [    RouterModule.forChild(myRoutes)  ],  exports: [    RouterModule  ],  providers: [    MyResolver  ]})export class MyModule { }

and you can access it in your Component like this:

///// ngOnInit() {    this.route.data      .subscribe((data: { mydata: myData }) => {        this.id = data.mydata.id;      });  }/////

And in the Route something like this (usually in the app.routing.ts file):

////{path: 'yourpath/:id', component: YourComponent, resolve: { myData: MyResolver}}////