Angular 4/5/6 Global Variables

AngularTypescript

Angular Problem Overview


I really struggle with creating global variables in my Angular 2 application.

So I have my file called globals.ts, which looks like this:

import { Injectable } from "@angular/core";


@Injectable()
export class Globals {

  var role = 'test';

}

And I want to use the variable role in my HTML view of my component like this:

{{ role }} 

I already added the globals.ts file to my app.module.ts in the following way:

providers: [
  Globals
],

No matter what I did on this file, it just didn't work. What I don't want to do is to have to import the globals.ts file in every component manually, which is why I want to use the providers feature.

Angular Solutions


Solution 1 - Angular

You can access Globals entity from any point of your App via Angular dependency injection. If you want to output Globals.role value in some component's template, you should inject Globals through the component's constructor like any service:

// hello.component.ts
import { Component } from '@angular/core';
import { Globals } from './globals';

@Component({
  selector: 'hello',
  template: 'The global role is {{globals.role}}',
  providers: [ Globals ] // this depends on situation, see below
})

export class HelloComponent {
  constructor(public globals: Globals) {}
}

I provided Globals in the HelloComponent, but instead it could be provided in some HelloComponent's parent component or even in AppModule. It will not matter until your Globals has only static data that could not be changed (say, constants only). But if it's not true and for example different components/services might want to change that data, then the Globals must be a singleton. In that case it should be provided in the topmost level of the hierarchy where it is going to be used. Let's say this is AppModule:

import { Globals } from './globals'

@NgModule({
  // ... imports, declarations etc
  providers: [
    // ... other global providers
    Globals // so do not provide it into another components/services if you want it to be a singleton
  ]
})

Also, it's impossible to use var the way you did, it should be

// globals.ts
import { Injectable } from '@angular/core';

@Injectable()
export class Globals {
  role: string = 'test';
}

Update

At last, I created a simple demo on stackblitz, where single Globals is being shared between 3 components and one of them can change the value of Globals.role.

Solution 2 - Angular

I use environment for that. It works automatically and you don't have to create new injectable service and most usefull for me, don't need to import via constructor.

  1. Create environment variable in your environment.ts

    export const environment = { ... // runtime variables isContentLoading: false, isDeployNeeded: false }

  2. Import environment.ts in *.ts file and create public variable (i.e. "env") to be able to use in html template

    import { environment } from 'environments/environment';

    @Component(...) export class TestComponent { ... env = environment; }

  3. Use it in template...

in *.ts ...

env.isContentLoading = false 

(or just environment.isContentLoading in case you don't need it for template)


You can create your own set of globals within environment.ts like so:

export const globals = {
    isContentLoading: false,
    isDeployNeeded: false
}

and import directly these variables (y)

Solution 3 - Angular

While all the other answers previously mentioned are correct. The Angular way would be is using either Pipes, Decorators or Components

If you simply want to display a string then use a component

Component

<Role></Role>

Decorator

If you want to do something like this:

<a href="/foo/{{userId}}/bar">Link</a>

You may want to implement your own decorator

<a [customHref]="[/foo/:userId/bar]">Link</a>

or if you use the built in router module with routerlink you could simply extend the RouterLink directive and implement your changes.

Pipe

somevariable = "this is my #:userId";
{{someVariable | applyglobals}}

And so on.

Solution 4 - Angular

I use environment variables in combination with other json files, i.e. to display build information and other stuff. That way, you can mix and/or re-use them in different environments.

// environment.ts, environment.prod.ts
export const environment = {
  
  ...
  appName: require('../../package.json').name,
  appVersion: require('../../package.json').version,

  ...
  globalX: require('../../globals.json').X,
  globalY: require('../../globals.json').Y,      
}

Usage:

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

export class FooterComponent implements OnInit {

  appName = environment.appName;
  buildVersion = environment.appVersion;
  x = environment.globalX;
  y = environment.globalY;
}

Solution 5 - Angular

Not really recommended but none of the other answers are really global variables. For a truly global variable you could do this.

Index.html

<body>
  <app-root></app-root>
  <script>
    myTest = 1;
  </script>
</body>

Component or anything else in Angular

..near the top right after imports:

declare const myTest: any;

...later:

console.warn(myTest); // outputs '1'

Solution 6 - Angular

You can use the Window object and access it everwhere. example window.defaultTitle = "my title"; then you can access window.defaultTitle without importing anything.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionA EView Question on Stackoverflow
Solution 1 - AngulardhiltView Answer on Stackoverflow
Solution 2 - AngularMartin SlavkovskyView Answer on Stackoverflow
Solution 3 - AngularPlaydome.ioView Answer on Stackoverflow
Solution 4 - AngularKurt Van den BrandenView Answer on Stackoverflow
Solution 5 - AngularPost ImpaticaView Answer on Stackoverflow
Solution 6 - AngularJustice AddicoView Answer on Stackoverflow