4

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";
}
1
  • your question is not clear as this doesnot state why are you using appsettings.json instead of environment.ts for angular application. usually appsettings.json is 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 Commented Dec 8, 2021 at 4:38

3 Answers 3

7

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

Sign up to request clarification or add additional context in comments.

Comments

2

You should follow these steps:

  1. Create a .env file in the root directory of your project and add environment-specific variables on new lines in the form of NAME=VALUE like this:
API_URL=http://localhost:45644/api/
  1. Use dotenv's tools that loads environment variables from a .env file into process.env object

  2. Install custom-webpack as a dev dependency:

npm install -D @angular-builders/custom-webpack
  1. Modify your Angular configurations – angular.json – to use the new builder (custom-webpack)
"projects": {
    "name-of-the-project": {
      //...
      "architect": {
        "build": {
          "builder":"@angular-builders/custom-webpack:browser"_,
          "options": {
            "customWebpackConfig": {
                "path":"custom-webpack.config.js"
            },
            //...
        //...
    } }
  1. Then, you are going to create your custom-webpack.config.js file at the root of your Angular Workspace and add the following content to retrieve your environment variables and pass them to your builder:
const webpack = require('webpack')
    require('dotenv').config()
    module.exports = {
      plugins: [
        new webpack.DefinePlugin({
          $ENV: {
            API_URL: JSON.stringify(process.env.API_URL),
          },
        }),
      ],
    }
  1. Finally to use your environment variables in Angular,you are going to add some typings, so that you can reference to your $ENV variable from webpack above within your Angular app.
  • First, let’s create a typing.d.ts file inside your src directory at the root of your workspace and add the following content:
declare var $ENV: Env;
    
    interface Env {
      API_URL: string;
    }
  • Then, inside the environment.ts, you need to read the environment variables passed to your application, so that your environment.ts would like this:
export const environment = {
  production: true,
  environment: $ENV.API_URL,
};
  1. And for using your environment variables on your components:
import { environment } from './../environments/environment';
...
public environment = environment.environment

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.