Reputation: 1453
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
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
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
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
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