Home > Software design >  Trying to set environment variables in appSettings.json - Angular and Typescript
Trying to set environment variables in appSettings.json - Angular and Typescript

Time:12-08

I am basically trying to set the API URL path in appSettings so I can change back and forth from prod and dev environments easily.

This is my appSettings.json file. apiURL is the variable I am trying to set and get.

{
 "Logging": {
"LogLevel": {
  "Default": "Information",
  "Microsoft": "Warning",
  "Microsoft.Hosting.Lifetime": "Information"
}
  },
 "AllowedHosts": "*",
 "apiURL": "http://10.241.2.68:8132/api"
}

Here is my page that is trying to access the environment variable that I set in appSettings.json.

import { Injectable } from '@angular/core';
// import { Defendant } from 'src/app/Models/Defendant';
import { Charge } from 'src/app/Models/Charge';
import { DefendantItem } from '../Models/DefendantItem';
import { Defendant_Charge } from '../Models/Defendant_Charge';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AppConfiguration } from "read-appsettings-json";  
@Injectable({
providedIn: 'root'
})
export class ChargeService {
//console.log(AppConfiguration.Setting().apiURL);
////////////////////////////////////////////////////////////////////
//  below is where I am trying to reference the environment variable
//  the entire program bombs and displays "GET \" on the page.
ChargeControllerUrl = AppConfiguration.Setting().apiURL   "/Charges";
//ChargeControllerUrl = "http://10.241.2.68:8132/api/Charges";
}

CodePudding user response:

As stated in comment, appsettings.json is not for angular application. here you can go through this tutorial to find necessary steps for using enviornment. here are some quick steps:

import { environment } from './../environments/environment';
...
const baseUrl: string = environment.baseUrl;

where environment.ts may look like

export const environment = {
  production: false,
  baseUrl: "http://localhost:45644/api/",
};

live example here

CodePudding user response:

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.

  1. Set up your app-settings.json (app-settings.qa.json, app-settings.prod.json) in assets/config folder

  2. 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;
  }
}

  1. 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

  • Related