akn
akn

Reputation: 3722

Injecting parametrized dependency and manual bootstrap in Angular

Before bootstraping my angular app I need to perform an async operation which returns some context for the application. Before starting, I need to init some 3rd party repository with these returned data, and then I'd like to inject this repository into on of my app's services. I'm looking for a proper, clean way of doing it, because the one that I currently have looks a bit hacky for me.

app.module.ts content:

let repo; //this is what i'd like to avoid

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        ReactiveFormsModule
    ],
    providers: [
        {
            provide: SomeService, useFactory: () => new SomeService(repo)
        }
    ],
    entryComponents: [AppComponent]
})
export class AppModule implements DoBootstrap {
    ngDoBootstrap(app: ApplicationRef) {

        //some async operation which returns context data
        setTimeout((data) => {
            repo = Some3rdPartyDatabaseSDK.init(data.token, data.repoConfig)
            app.bootstrap(AppComponent);
        }, 3000);
    }
}

Can it be done better?

Upvotes: 0

Views: 192

Answers (1)

Plochie
Plochie

Reputation: 4117

For this scenarios you should use, APP_INITIALIZER, This function is called when angular app is initialized.

Angular will execute provided function when the app is initialized. Angular will wait for the initialization if the function returns a promise until the promise resolved.

  1. Create AppLoadService in your project
  2. Create initialization method in service. (this method should return promise)
  3. Create function which will refer init method in module.
  4. setup APP_INITIALIZER in providers.

DEMO (Application will initialize after 5s)

app-load.service.ts

@Injectable()
export class AppLoadService {

  repo: any;

  init(): Promise<any> {

    return new Promise((resolve, reject) => {

      console.log('App is yet to initialize');

      setTimeout(() => {
        console.log('App initialized');
        this.repo = 'some value';
        resolve();
      }, 5000);
    });
  }

}

app.module.ts

import { NgModule, APP_INITIALIZER } from '@angular/core';

function init_app(appLoadService: AppLoadService) {
    return () => appLoadService.init();
}

@NgModule({
  providers: [
    AppLoadService,
    { provide: APP_INITIALIZER, useFactory: init_app, deps: [AppLoadService], multi: true }
  ]
})
export class AppModule { }

Upvotes: 1

Related Questions