23

I have a global js variable defined below (@Url is an ASP.Net MVC html helper it will get converted to a string value):

<script>
  var rootVar = '@Url.Action("Index","Home",new { Area = ""}, null)';
  System.import('app').catch(function(err){ console.error(err); });
</script>

How do I access rootVar in an angular2 component? I used to use the window service in angular 1.5, is there an analogous way of doing that in angular2?

Specifically, I want to use that rootVar variable to help generate the templateUrl in this component:

import { Component, Inject} from '@angular/core';

@Component({
    selector: 'home-comp',
    templateUrl: '../Home/Root'
})

export class HomeComponent {   
    constructor( ) {  }
}
cobolstinks
  • 6,801
  • 16
  • 68
  • 97
  • 1
    If it's global, it's global. That means that any piece of JS code can access the variable. – JB Nizet Jun 06 '16 at 16:50
  • 1
    You can look at this Thierry`s answer http://stackoverflow.com/questions/37337185/passing-asp-net-server-parameters-to-angular-2-app/37384405#37384405 – yurzui Jun 06 '16 at 16:50

6 Answers6

37

Within your component you could reference window to access the global variables like so:

rootVar = window["rootVar"];

or

let rootVar = window["rootVar"];
Riyaz Sayyad
  • 531
  • 1
  • 5
  • 8
13

You need to update the file that bootstraps your application to export a function:

import {bootstrap} from '...';
import {provide} from '...';
import {AppComponent} from '...';

export function main(rootVar) {
  bootstrap(AppComponent, [
    provide('rootVar', { useValue: rootVar })
  ]);
}

Now you can provide the variable from the index.html file this way:

<script>
  var rootVar = '@Url.Action("Index","Home",new { Area = ""}, null)';
  System.import('app/main').then((module) => {
    module.main(rootVar);
  });
</script>

Then you can inject the rootVar into components and services this way:

import { Component, Inject} from '@angular/core';

@Component({
  selector: 'home-comp',
  templateUrl: '../Home/Root'
})
export class HomeComponent {   
  constructor(@Inject('rootVar') rootVar:string ) {  }
}
GillesC
  • 10,647
  • 3
  • 40
  • 55
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thanks, I was able to access the variable in my component following your example, but I'm running into a new problem. Now that i have the rootVar being injected into the constructor I can't seem to use it to modify the component templateUrl. @Component({ selector: 'home-comp', templateUrl: '..{{baseUrl}}Home/Root' }) export class HomeComponent { baseUrl: string; constructor( @Inject('rootVar') rootVar: string) { this.baseUrl = rootVar; } } – cobolstinks Jun 06 '16 at 17:32
  • You're welcome! In fact, you can't use the variable this way to build the tempalteUrl path. One is at the level of the class and other of the instance... In your case, I would try to extend the UrlResolver class and inject your variable in it. See this link: https://angular.io/docs/ts/latest/api/compiler/UrlResolver-class.html. – Thierry Templier Jun 06 '16 at 17:40
10

In the component file, outside component class definition, declare rootVar, and it will become available in the component constructor:

declare var rootVar: any;

then

@Component(...)
export class MyComponent {
  private a: any;

  constructor() {
    this.a = rootVar;
  }
}
Dmitriy
  • 525
  • 5
  • 11
  • 1
    Important to note. I could not get the declare outside of the component class to be visible to any methods in the component class. You need to set an instance variable in constructor to reference the global variable and then reference that variable in your methods – hewstone Mar 27 '17 at 13:35
7

Here don't forget to wash your hands... Angular is just javascript

//Get something from global
let someStuffFromWindow= (<any>window).somethingOnWindow;

//Set something
(<any>window).somethingOnWindow="Stuff From Angular";

This is bad for some reason.. you should feel bad!

Go ahead and use that find and replace fuction for window. with (<any>window).

konzo
  • 1,973
  • 22
  • 32
  • `window['somethingOnWindow']` looks cleaner. Don't ask me why – redent84 Apr 18 '18 at 08:52
  • why? @redent84 `(sorry couldn't help it)` – konzo Apr 18 '18 at 09:50
  • I think in general `[]` is used for dynamic fields. Using `property.value` is used for none dynamic fields (see airbnb styleguide). – Aaron Rabinowitz Jan 02 '19 at 18:36
  • 2
    Thanks. Had to search for a long time to find a solution without 5 files and 40 lines of code. – Jonathan Muller May 20 '19 at 06:33
  • @JonathanMuller Please thank by upvoting, also you should be using ```window['somethingOnWindow']``` see comments above... I haven't deleted this answer because it is technically correct just not recommended – konzo May 20 '19 at 07:42
  • 1
    I prefer with the type casting, so it looks a bit complicated to fit with the rest of the code, and I can pretend I do smart Typescript – Jonathan Muller May 21 '19 at 00:30
3

A different approach would be to export your var, for ex:

  export var API_ENDPOINT = '@Url.Action("Index","Home",new { Area = ""}, null)';

and then import that in your component

import {API_ENDPOINT }
null canvas
  • 10,201
  • 2
  • 15
  • 18
0

In HTML template you can use method get

<span>{{getGlobalData('rootVar')}}</span>

And create method in component like:

get getGlobalData() {
    // Closure workaround
    return function(rootVarName) {
        return window[rootVarName];
    }
}