SKL
SKL

Reputation: 1453

How to inject application config into app module in angular

I am using Angular v16 and I have the following config that needs to be included in app.module. What is the best way to inject appConfig in app.module? It works if I include them directly inside app.module providers, but I want to manage all the dependencies in a separate config file.

Note: I'm not using standalone component for app.component.ts. So I can't use bootstrapApplication to to inject them

app.config.ts

export const appConfig: ApplicationConfig = {
   providers: [
     provideAnimations(),
     provideHttpClient(),
     provideRouter(
        appRoutes,
        withInMemoryScrolling({scrollPositionRestoration: 'enabled'}),
     ),
   ]
}

main.ts

platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .catch((err) => console.error(err));

Upvotes: 6

Views: 27168

Answers (4)

Dev Gaud
Dev Gaud

Reputation: 844


import {bootstrapApplication} from '@angular/platform-browser';
import {appConfig} from './app/app.config';
import {AppComponent} from './app/app.component';

bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));

You can pass your config like this.

Upvotes: 0

Bytech
Bytech

Reputation: 1215

I remember having trouble with config not getting loaded in time, and solving it using a service and HttpBackend (it "dispatches requests directly to the backend, without going through the interceptor chain.")

ConfigService

export class ConfigService {

  private appConfig: Config

  // Using handler: HttpBackend in constructor, this way synced config init can use httpClient
  private httpBackEnd: HttpClient

  constructor(
    public handler: HttpBackend
  ) {
    this.httpBackEnd = new HttpClient(handler)
  }


  loadConfig() {
    return this.httpBackEnd.get<Config>('config.json')
      .toPromise()
      .then(
        (config: Config) => { this.appConfig = config },
        (err) => { console.log('Failed to load config.json. ' + err) }
      )
  }

  get params() {
    if (!this.appConfig) { throw Error('Trying to use config, but it was not yet loaded!') }
    return this.appConfig
  }
}

And then, in app.module, calling loadConfig in a provider:

@NgModule({
  declarations: [...],
  imports: [...],
  providers: [
    {
      provide: APP_INITIALIZER,
      multi: true,
      deps: [ConfigService],
      useFactory: (config: ConfigService) => {
        return () => {
          return config.loadConfig()
        }
      }
    }
  ]
})

Example of config.json

{
  "api": {
    "domain": "http://homestead.test/",
    "route": "/v4"
  },
  "logoutRedirectPath": "/user/login",
  "devMode": false
}

The properties defined inside config.json are then available everywhere I import ConfigService and accessing e.g. this.configService.params.api.domain.

The other advantage is, the config can be updated, and the app does not need to be recompiled to take effect.

Upvotes: 4

Eli Porush
Eli Porush

Reputation: 1567

If I understand you right - this is the suitable place to use forRoot() static method concept, see this example:

import { NgModule } from '@angular/core';
import { AppConfigService } from './app-config.service';

@NgModule({
  providers: [AppConfigService],
})
export class AppModule{
  static forRoot(config: AppConfig): ModuleWithProviders<AppModule> {
    return {
      ngModule: AppModule,
      providers: [{ provide: AppConfig, useValue: config }],
    };
  }
} 

in this way, you can inject from the outside the configuration you need and it will be loaded into the module. to implement it, you simply do this:

platformBrowserDynamic()
.bootstrapModule(AppModule.forRoot(YOUR CONFIGURATION OBJECT))
.catch((err) => console.error(err));

let me know if it works for you :)

Upvotes: 0

Francesco Moro
Francesco Moro

Reputation: 380

You should just import your constant into app.module.ts.

import { appConfig } from './app.config';

And then use it like this:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { appConfig } from './app.config';

@NgModule({
  ...appConfig
})
export class AppModule { }

If you want to define all the app metadata into your constant (imports, providers, exports, etc...) Make sure your AppConfig interface matches the one required info NgModule decorator one (more info here.)

Upvotes: -1

Related Questions