Reputation: 2981
We would like to call a rest api when angular 2 app being bootstrapped, i mean first thing it should do about the application is call this api and get some data which is required for application.
Is there anyway to achieve this? I saw following article but it was meant for beta version of Angular 2
Sample Code based on Angular 2 beta or rc
Reading data before app start up
Upvotes: 53
Views: 27651
Reputation: 141
One thing I came across using the answer provided by Santanu is that it won't work unless StartupService
is defined in the providers before the APP_INITIALIZER
. I'm using Angular 4.x
, so the providers part looks like this in my case:
providers: [
UserService,
{
provide: APP_INITIALIZER,
useFactory: userServiceFactory,
deps: [UserService],
multi: true
}
]
Upvotes: 13
Reputation: 43
@efirvida & @Santanu Biswas
I tried your answer and it works (content in APP_INITIALIZER happens before app.component bootstrapping).
Unfortunately, the injections in all components happen before it, so that components refer to variables not ready yet.
I opened a question here.
It is basically the same question that @magos asked.
Any help well accepted ^^
The only solution I can think of is to make API calls in app.component to get config data, but is not properly what is needed for both OP and me. Will be my solution if I can't solve the syncronism issue
Upvotes: 0
Reputation: 111
Here is an article which explains APP_INITIALIZER in much more detail and it also shows how angular uses it.
Upvotes: -2
Reputation: 4787
You can use APP_INITIALIZER to call a service method at bootstrap. You will require to define a provider
for it in your AppModule
.
Here is an example of how to do this.
StartupService (startup.service.ts)
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
@Injectable()
export class StartupService {
private _startupData: any;
constructor(private http: Http) { }
// This is the method you want to call at bootstrap
// Important: It should return a Promise
load(): Promise<any> {
this._startupData = null;
return this.http
.get('REST_API_URL')
.map((res: Response) => res.json())
.toPromise()
.then((data: any) => this._startupData = data)
.catch((err: any) => Promise.resolve());
}
get startupData(): any {
return this._startupData;
}
}
AppModule (app.module.ts)
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { StartupService } from './startup.service';
// ...
// Other imports that you may require
// ...
export function startupServiceFactory(startupService: StartupService): Function {
return () => startupService.load();
}
@NgModule({
declarations: [
AppComponent,
// ...
// Other components & directives
],
imports: [
BrowserModule,
// ..
// Other modules
],
providers: [
StartupService,
{
// Provider for APP_INITIALIZER
provide: APP_INITIALIZER,
useFactory: startupServiceFactory,
deps: [StartupService],
multi: true
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
AppComponent (app.component.ts)
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { StartupService } from './startup.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(private router: Router, private startup: StartupService ) { }
ngOnInit() {
// If there is no startup data received (maybe an error!)
// navigate to error route
if (!this.startup.startupData) {
this.router.navigate(['error'], { replaceUrl: true });
}
}
}
Upvotes: 113