Reputation: 359
I need to load data from a service which contains environment data. I need some of that data for a module in app.modules
.
Here's a small app.modules.ts
example:
import { CustomEnvironmentService } from './CustomEnvironmentService';
let customService: CustomEnvironmentService;
@NgModule({
declarations: [...],
imports: [CustomModule.forRoot(customService.ENVIRONMENT_DATA)],
providers: [...]
})
export class AppModule {}
First thing to notice is that customService.ENVIRONMENT_DATA
is just a public variable in CustomEnvironmentService
which gets information from an environment config file called env.js
.
The problem is that when the app loads customService.ENVIRONMENT_DATA
is undefined. This is understandable as I'm pretty sure the service isn't initialized and hasn't fetched the data.
I found something called APP_INITIALIZER
but it appears that I may not be able to use it to read from either that env.js
file or will it use my CustomEnvironmentService
(which gets the data from env.js
).
I'm also basing my implementation on this article: How to use environment variables to configure your Angular application without a rebuild
Any ideas?
Upvotes: 5
Views: 7069
Reputation: 12052
Using the approach from the article you link you cannot use an APP_INITIALIZER
because they get called after all the imported modules have initialized what you already discovered.
Since this approach just sets the environment settings as a global window property __env
you can just define a global constant in Angular that you assign the value of the environment settings from the window. Then it will be available in all the application. This will be available also immediately when the application starts.
For example you create an environment-data.ts
file with the following content:
export const ENVIRONMENT_DATA = window['__env'];
Then just import the constant where you need it and use it.
import { ENVIRONMENT_DATA } from './environment-data';
@NgModule({
declarations: [...],
imports: [CustomModule.forRoot(ENVIRONMENT_DATA)],
providers: [...]
})
export class AppModule {}
Upvotes: 6
Reputation: 922
I'm not sure on the exact timings as to when it runs but you can read from a file using APP_INITIALIZER.
app.module.ts
export function startupServiceFactory(startupService: StartupService) {
return () => startupService.load();
}
@NgModule({
...
providers: [
StartupService,
{
provide: APP_INITIALIZER,
useFactory: startupServiceFactory,
deps: [StartupService],
multi: true
}
]
})
startup.service.ts
export class StartupService {
// I just use private properties on the class to hold the returned values
private localStartupData: any;
constructor(private httpClient: HttpClient){}
load(): any {
// I'm returning a txt file so I have to set the responseType to text
this.httpClient.get('<relativePathToFile>/env.js', { responseType: 'text' })
.pipe(
catchError((err) => {
// If I have any defaults in case of file not existing I set them here
return throwError(err);
})
)
.toPromise()
.then((data: any) => {
this.localStartupData = data;
})
.catch((err: any) => {
Promise.resolve();
});
}
get startupData(): any {
return this.localStartupData;
}
}
Just make sure that env.js is included in your angular.json
Upvotes: 0