How to use environment variable in index.html for Angular 6
Asked Answered
A

10

71

I am using angular6, in my project I am using Facebook Account Toolkit for mobile verification purpose.

I need to initialise Account toolkit in index.html file using following code.

  AccountKit.init({
   appId:"XX",
   state:"xx",
   version:"v1.2",
   fbAppEventsEnabled:true,
   debug:true
 });

The problem is, values for appId and state change depending on environment (development/test/production).

How can I use environment variables in index.html file.

Please let me know if anyone has a solution for angular 6.

Aron answered 28/8, 2018 at 5:13 Comment(0)
A
94

You should create copy of index.html and name it index.someenv.html. Then in your angular.json in environment configuration setup file replacement:

"fileReplacements": [
    {
        "replace": "src/index.html",
        "with": "src/index.someenv.html"
    }
]

The angular cli will replace these files when you run your build

UPD: For Angular 8+ use this:

Add the following to your angular.json:

"production": {
  "index": {
    "input": "src/index.someenv.html",
    "output": "index.html"
  },
},
Affusion answered 17/9, 2018 at 16:1 Comment(7)
I am doing this but for some reason it still copies over the original index.html file. I am using the following command to build the angular app: ng build --prod -c production --output-path dist. Do you have any idea why it wouldn't replace the index.html file with index.prod.html ?Nylanylghau
@DejanBogatinovski can you show your configuration for production? (in angular.json)Affusion
Here it is: dropbox.com/s/jysqkn9pf5z39y4/Screenshot_1.png?dl=1Nylanylghau
I am facing the same issue with replacing index ("index.html" not getting replaced with "index.prod.html"). However, this solution is working for {"replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" }.Biped
@JosephHorsch only the content of index.html will be replaced, not the filename.Affusion
@DejanBogatinovski As of angular 8, you can't replace index files via "fileReplacements". You have to specify your own index file via "index" property. Eg.: "index":"src/index.someenv.html".Pincenez
See my answer for Angular 8 and aboveFarrish
F
50

This answer supersedes Artyom's answer for Angular 8 and above. Add the following to your angular.json:

"production": {
  "index": {
    "input": "src/index.someenv.html",
    "output": "index.html"
  },
},
Farrish answered 30/5, 2020 at 15:9 Comment(1)
This would also be great to do in a CI build. have index.tokens.html contain MY_PLACEHOLDER. index.html contains the default for local development, and in your pipeline just before your prod build do a replacement of MY_PLACEHOLDER with a pipeline variable. This allows values like environment URLs to be stored in the pipeline and a change to them would be to simply re-run the pipeline for a given commit to generate the file with the new URL instead of needing a code change to have to be promoted through various environments.Monopolist
T
6

In main.ts file you can use document.write(environment.variable) and it will write what you want in index.html

(I use it to make the Google Analytics script take a dynamic Tracking ID wether it's in development or production mode, and it works well in Angular6)

Tabaret answered 7/5, 2019 at 9:26 Comment(1)
Hi, would you have a small example to show how you managed to update your Analytics script Tracking ID in your index.html file? Much appreciatedAnybody
H
6

An example here for document.write(environment.variable) : https://github.com/angular/angular-cli/issues/4451#issuecomment-285026543

import { environment } from './environments/environment';

if (environment.production) {
  document.write('<script type="text/javascript">// ProductionAnalyticsCodeHere</script>');
} else if (environment.staging) {
  document.write('<script type="text/javascript">// StagingAnalyticsCodeHere</script>');
}
Hamate answered 18/10, 2019 at 7:47 Comment(1)
This one is kinda dangerous, because document.write will replace whole HTML document if invoked after page is being loaded.Lalla
P
6

for me above answers did not work on Angular 10, so I created different folder for staging, production etc and placed the index.html which was used by CLI as per the build environment

{
  "projects": {
    "yourApp": {
      "projectType": "application",
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "index": "src/index.html",
          },
          "configurations": {
            "production": {
              "index": "src/production/index.html",
            }
          }
        }
      }
    }
  }
}     
Parisi answered 14/4, 2021 at 12:7 Comment(3)
I confirm, This solution worked for me, on angular 13Lightner
OK, that's weird. I was set to also confirm that jscroll's solution didn't work in Ang 13/14: (Index html generation failed \r\n ENDENT: no such file or directory, open C:\blah\blah\ClientApp\src\index.test.html), but after I successfully followed this solution and then tried it again (just to test/report whether it was the name of the index file or whether it needed to be in its own folder), jscroll's solution started working. Go figure.Bestow
This worked for the default(index.html), but for the dev(index.dev.html), I also had to do mv dist/index.dev.html dist/index.htmlSophrosyne
K
2

Avoid direct access to the document object by injecting DOCUMENT to your AppComponent.

import { DOCUMENT } from '@angular/common';
...
  public constructor(
    @Inject(DOCUMENT) private doc: any
  ) {

Add the tag in ngOnInit()

ngOnInit() {
    this.setYourScriptTag();
}

private function to set it

  private setYourScriptTag() {
    const s = this.doc.createElement('script');
    s.type = 'text/javascript';
    s.innerHTML = `AccountKit.init({
   appId: "${environment.appId}",
   state: "${environment.state}",
   version:"v1.2",
   fbAppEventsEnabled:true,
   debug:true
 });`;
    const head = this.doc.getElementsByTagName('head')[0];
    head.appendChild(s);
  }

This answer is from edodusi

https://github.com/angular/angular-cli/issues/4451#issuecomment-384992203

Katz answered 23/10, 2020 at 21:22 Comment(0)
C
2

Angular 16: File replacement approach

"production": {
       "index": "src/index.html",
},
"development": {
       "index": "src/index.development.html",
}

Using two different HTML file

Carbineer answered 2/11, 2023 at 8:22 Comment(0)
S
1

I think you can do it all in main.ts

const env = environment;

 AccountKit.init({
   appId:env.appId,  // this lane
   state:env.state,  // this lane
   version:"v1.2",
   fbAppEventsEnabled:true,
   debug:true
});

Thanks.

Sphygmoid answered 15/10, 2018 at 3:2 Comment(1)
I had a similar issue with loading google charts js and needing to pass the correct api from the environment variables. Moving the initialize call to main.ts worked for me. Of course timing issues are always a concern when loading/initializing scripts so let us know if it works in your scenario.Pudendum
C
0

I added this in main.ts:

var html = document.documentElement.innerHTML
document.documentElement.innerHTML = html.replace("Replace me!", environment.variable)

Note that the old value will still exist in index.html for some time while the page is initially loading. (For example, use this to replace the page title and you'll see the old value displayed before the replace happens.)

Caulicle answered 12/12, 2019 at 0:18 Comment(1)
FWIW: There is an alternate for setting the title that does not suffer from above @Caulicle mentioned latency, per the Angular docs - angular.io/guide/set-document-title.Pol
P
-5

import your environment file into .ts file.

import { environment } from '../../environments/environment';

Create required fields in your class, assign values from environment to these variables in the constructor, use usual binding in the .html file.

.ts

import { Component } from '@angular/core';
import { environment } from '../environments/environment';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public production = true;
  constructor() {
    this.production = environment.production;
  }
}

.html

<span>{{production}}</span>
Pamper answered 28/8, 2018 at 6:57 Comment(1)
thanks, Igor Litvinovich, but I want to use that env variable in index.html , not in .ts file to that particular html file, i am using angular6. and import not working in index.html file.Aron

© 2022 - 2024 — McMap. All rights reserved.