Changing the environment variable in an Angular application with user input

I'm currently in the process of developing an angular application that interacts with a REST API on the backend server. The URL for this server is currently set as an environment variable like so:

export const environment = {
  production: false,
  loggerLevel: NgxLoggerLevel.DEBUG,
  disableConsoleLogging: false,
  lang: 'en',
  api: {
    . //other variables
    .
    .
    host: "http://mycoolurl.com/rest/v11_1/",
    . 
    . //more variables
    .
  }
};

A similar question addressing this issue can be found here. However, it involves using a specific settings.json file fetched via APP INITIALIZER. Another related query can be viewed here, recommending the use of a separate JSON file.

A recent change request now demands that users have the ability to specify the target URL for the REST calls. Ideally, this should be facilitated through an input field where users can enter the desired URL, updating the host in the environment file accordingly. So, how do I go about achieving this?

Regrettably, completely revamping the implementation and removing the host from the environment file is not feasible, considering its widespread usage across the application.

Answer №1

If you attempt to directly modify the environment value within the code, you will run into issues as it is closely intertwined with other components. This method is not recommended because any updates to the application would simply overwrite the value. It is advisable to store the environment separately on the server side!

Approach A:

To change the environment value, utilize the APP_INITIALIZER and update it after loading:

environment.api.host = loadedValue

This tactic will work effectively only if you do not access the value prior to this alteration. The value may be accessed before this point if referenced in module definitions, configurations, or classes injected into the initializer.

Approach B

While a bit cumbersome, this method can also be effective:

Store the API URL in a separate JavaScript file structured similarly to this:

window.userEnvironment = { host: "http://custom-host" };

Include this JavaScript file in the <head> section of the index.html using:

<script src="user-env.js"></script>
. This ensures that it is loaded prior to Angular's initialization by the browser itself.

Subsequently, inside the environment.ts file, you can execute the following:

export const environment = {
  ...
};

const userEnv = (window as any).userEnvironment;
if (userEnv) Object.assign(environment, userEnv);

By implementing this code snippet, you effectively replace the environment values with those from the user-env.js file.

This operation does not necessarily have to take place within the environment file; it could be executed elsewhere. Just ensure that it transpires before the utilization of environment. Additionally, if multiple environments are being utilized, this process must be replicated across all corresponding environment files.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to turn off the annoying pop-up messages that show up for input validation, specifically the one that says "Please complete

Currently using Angular 2, my form has input fields similar to this simplified version: <input class="body-text1" type="text" [(ngModel)]="model.name" name="name" required minlength="1"> <!--more inputs like this --> Although I have implement ...

Converting a TypeScript array into a generic array of a specific class

I am attempting to convert a JSON source array with all string values into another array of typed objects, but I keep encountering errors. How can I correct this code properly? Thank you. Error 1: There is an issue with converting type '({ Id: string ...

Encountered an error while trying to install @material-ui/core through npm: Received an unexpected end of JSON input

npm install @material-ui/core npm ERR! Unexpected end of JSON input while parsing near '...X1F+dSMvv9bUwJSg+lOUX' npm ERR! A complete log of this run can be found in: npm ERR! C:\Users\WR-022\AppData\Roaming\npm-cach ...

Verifying a data field in a document in Cloud Firestore for a particular value

Is there a way to validate the existence of a username in my Users Collection before allowing user registration? The usernames are stored on user documents in Firestore. https://i.stack.imgur.com/WARAs.png I'm looking for a snippet or solution that ...

ERROR : The value was modified after it had already been checked for changes

Encountering an issue with [height] on the main component and seeking a solution Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '753'. Current value: '731'. I have th ...

Kendo's comboBox for local virtualization

Looking to implement virtualization for local data using the kendo object ComboBox. I've tried different methods, but only the current page (first 40 elements) is displayed. I followed a code structure similar to the kendo virtualization tutorial an ...

How can I reload a form page in Angular 9 after making a POST request with HttpClient?

I'm currently working on an Angular 9 application and am facing an issue with refreshing the page after making a POST request using HttpClient. Below is my form and its corresponding component: <form #myForm="ngForm" (ngSubmit)="save(myForm)"> ...

Creating TypeScript Classes - Defining a Collection of Objects as a Class Property

I'm trying to figure out the best approach for declaring an array of objects as a property in TypeScript when defining a class. I need this for a form that will contain an unspecified number of checkboxes in an Angular Template-Driven form. Should I ...

Page Breaks - Patience in anticipation of dataSource readiness

I am facing an issue with my pagination service and component. The dataSource appears empty when the page is loaded for the first time, but by the second time it is populated and I can display the dataTable and paginate successfully. Is there a workaround ...

Methods to validate CSS attributes specified within a class using React testing library

I am struggling to validate the CSS properties defined within a class in CSS using the React Testing Library. Unfortunately, I am facing challenges in doing so. Here are the simplified code snippets: import React from "react"; import { render, ...

After making a change to a Vue or JavaScript file, running `npm run watch` causes a crash due to the `compileTemplate` function now requiring

I am facing an issue where both npm run dev and prod are functioning correctly, but when I attempt to run watch and make changes to files, npm run watch throws an error and crashes. I am using laravel mix with TypeScript, and my webpack mix parameters are ...

The query parameters and URL are failing to update properly

constructor( private router: Router, private activatedRoute: ActivatedRoute, ) {} ngOnInit() { this.activatedRoute.queryParams.subscribe(params => { //subscribe to param change console.log('params', params) } upd ...

How can I retrieve user group information from Keycloak in my Angular application?

While it is common knowledge that Keycloak stores user information in local storage for easy access to username and email, I am curious about how to retrieve details regarding the group(s) a user is associated with. Can anyone provide insights on this? ...

Unable to bring in a TypeScript library that was downloaded from a GitHub fork repository

Currently, I am working on developing a GitHub app using the probot library. However, I have encountered an obstacle as outlined in this particular issue. It seems that probot does not offer support for ESM modules, which are crucial for my app to function ...

Warning from Google Chrome: Ensure password forms include optional hidden username fields for improved accessibility

Upon visiting the "reset password" route of my single-page application and checking the Chrome browser console, I am presented with a warning message: [DOM] Password forms should contain (optionally hidden) username fields for accessibility: (More info: g ...

After saving any HTML, SCSS, or TS file, Angular 12 does not compile immediately

Recently I upgraded my Angular project from version 8 to 12 and then migrated to eslint. However, I have encountered an issue where the compilation does not begin immediately after saving a file. There is a delay of approximately 2 minutes before the compi ...

Extracting data from an array using Angular

Currently, I am developing an Angular application that involves handling an array structured like the one below. [ { Code: "123", Details:[ { Id: "1", Name: "Gary" }, { ...

Display an API generated popup list using Vue's rendering capabilities

I'm attempting to generate a pop-up within a displayed list using custom content retrieved from an API request. Currently, my code looks like this: <template> <div class="biblio__all"> <a v-for="i in items" ...

Encountered an issue while attempting to authenticate CMS signature using pkijs

I am attempting to validate a CMS signature generated with open ssl using the following command: $ openssl cms -sign -signer domain.pem -inkey domain.key -binary -in README.md -outform der -out signature Below is my code utilizing pkijs: import * as pkij ...

Displaying a collection of nested objects in AngularRendering a group

Is there a way to render an object of objects in Angular without converting it into an array or similar structure? I have a large object of objects and I want to avoid multiple iterations through object-to-array conversions just to loop through the array i ...