I would suggest not using environment.ts since this is a build time configuration.
What you are actually looking for is some way to fetch your app-settings.json file depending on the environment, at run time. This means you can package your code and promote the packaged code through your environments, without rebuilding.
Angular has something called APP_INITIALIZER which you can use to achieve this.
Set up your app-settings.json (app-settings.qa.json, app-settings.prod.json) in assets/config folder
Configure an AppConfigService angular service.
//app/services/app-config.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class AppConfigService {
private appConfig: any;
private http : HttpClient;
constructor(http: HttpClient) {
this.http = http;
}
loadAppConfig() {
return this.http.get('/assets/config/app-settings.json')
.toPromise()
.then(config => {
this.appConfig = config;
});
}
get apiBaseUrl() : string {
return this.appConfig.apiBaseUrl;
}
}
- Configure the AppService using the APP_INITIALIZER as the injection token in your AppModule
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { AppConfigService } from './services/app-config/app-config.service';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
{
provide : APP_INITIALIZER,
multi : true,
deps : [AppConfigService],
useFactory : (appConfigService : AppConfigService) => () => appConfigService.loadAppConfig()
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
Now you can use this service to fetch the baseURL using dependency injection
Below is an example service, what yours might look like. Note the constructor and the apiUrl private class variable
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { IempList } from '../interfaces/iemp-get-res';
import { map } from 'rxjs/operators';
import { AppConfigService } from 'src/app/services/app-config/app-config.service';
@Injectable({
providedIn: 'root'
})
export class EmpService {
constructor(private httpClient: HttpClient, private appConfigService: AppConfigService) { }
private apiUrl = this.appConfigService.apiBaseUrl + '/api/employee';
public getEmp(): Observable<IempList> {
return this.httpClient.get(this.apiUrl)
.pipe(map((res: IempList) => res));
}
public deletEmp(id): Observable<any> {
return this.httpClient.delete(this.apiUrl + '/' + id)
.pipe(map((res: any) => res));
}
public createEmp(formData): Observable<any> {
return this.httpClient.post(this.apiUrl + '/create', formData.data)
.pipe(map((res: any) => res));
}
public editEmp(formData): Observable<any> {
return this.httpClient.post(this.apiUrl + '/update', formData.empData)
.pipe(map((res: any) => res));
}
}
from here, you will need to use your deployment method (azure devops pipelines, for example) to rename the appropriate file in the assets folder according to your env
qa: rename app-settings.qa.json -> app-settings.json
prod: rename app-settings.prod.json -> app-settings.json
And with that you will have a runtime app config
appsettings.jsoninstead ofenvironment.tsfor angular application. usuallyappsettings.jsonis used for .Net Core application and if you are using .net core and angular template then you need to use environment.ts in your clientapp directory