11

I have a global constants like root directory that I want every component to have access to. In another stackoverflow question the answer was to create a constants class and import that to every component.

Is there a way to bootstrap a constants class so that every component in the app has access to it without any additional importing?

I have this so far but it is not working, how do I boostrap the constants class and then access then in my components?

constants.ts

export class Constants{
  root_dir: string;

  constructor(){
      this.root_dir = 'http://google.com/'
    }
  }

main.ts

import {bootstrap} from 'angular2/platform/browser'
import {Constants} from './constants'

bootstrap([
  provide(Constants, {useClass: Constants})
]);

random.component.ts

import {Component, bind} from 'angular2/core';
import {Injector} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: `{{test}}`
})

export class RandomComponent{
    test: string;

    constructor(){
        this.test = injector.get(Constants.root_dir);
    }
}
ClickThisNick
  • 5,110
  • 9
  • 44
  • 69
  • You're right there. You just have to pass `Constants` through the constructor : `constructor(constants: Constants) {}` (you'll have to import it anyway or TS will complain. – Eric Martinez Mar 06 '16 at 03:42

3 Answers3

9

To answer your questions:

  • All components using the Constants class will need to import your constants file.

  • In order to use the Constants class you need to inject it into the constructor of any consuming components, removing the injector.get() function from random.component.ts like so:

export class App {
  constructor(constants: Constants) {
    this.url = constants.root_dir;
  }
}

You may also decorate your constant class as an @Injectable and @Inject it into the constructor of your component.

Here is a working plunker.

It is beneficial to bootstrap the shared constants at the app level so that only one instance of the class is created and shared among all components.

pxwise
  • 1,350
  • 15
  • 16
  • Is there any benefit to injecting it into the constructor? Is that what makes it so only on instance is created? – ClickThisNick Mar 06 '16 at 13:00
  • DI makes it easy to configure and therefore easy to test. Otherwise it's hardcoded and testing can become quite cumbersome. – Günter Zöchbauer Mar 06 '16 at 13:11
  • @ClickThisNick it is the recommended pattern to get maximum DI flexibility for testing, ngUpgrade and use of forwardRef, see http://stackoverflow.com/a/35351649/1774183 – pxwise Mar 06 '16 at 23:52
2
import {Component,bind,provide} from 'angular2/core';

import {bootstrap} from 'angular2/platform/browser';
import {FORM_DIRECTIVES} from 'angular2/form';
import {Directive, ElementRef, Renderer, Input,ViewChild,AfterViewInit} from 'angular2/core';
import {Constants} from 'src/constants'
import {ViewChild, Component, Injectable} from 'angular2/core';

@Component({
selector: 'my-app', 
  template: `{{test}}`,
})


export class App {
    test: string;

    constructor(cs:Constants){
        this.test = cs.root_dir;
    }
}

bootstrap(App, [Constants]);

Demo

micronyks
  • 54,797
  • 15
  • 112
  • 146
0
import {Component} from 'angular2/core'
import { Constants } from './constants'

@Component({
    selector: 'test',
    template: `  
                    Constants: <strong>{{ urlTemplate }}</strong>

              `
    providers:[Constants]

})

export class AppComponent{

  constructor(constants: Constants){
    this.urlTemplate = constants.root_dir;
  }

}

You can use adding Constants in providers:[Constants]


The decorator @Injectable It is not necessary in this case, but Google recommends always use You can see here: https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#why-injectable-


/*
We recommend adding @Injectable() to every service class, even those that don't have dependencies and, therefore, do not technically require it. Here's why:
Future proofing: No need to remember @Injectable when we add a dependency later.
Consistency: All services follow the same rules, and we don't have to wonder why a decorator is missing
*/

//@Injectable() 
export class Constants{
  root_dir: string;

  constructor(){
      this.root_dir = 'http://google.com/'
    }
  }

Plunker


About @Inject used, you can read something here: what is the difference between using (@Inject(Http) http: Http) or not


Now if you want this globally can add in bootstrap

//main entry point
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app';
import { Constants } from './constants';


bootstrap(AppComponent, Constants)
  .catch(err => console.error(err));

//import { Injectable } from 'angular2/core'

//@Injectable()
export class Constants{
root_dir: string;

  constructor(){
      this.root_dir = 'http://google.com/'
    }
  }

import {Component, Inject} from 'angular2/core'
import { Constants } from './constants';

@Component({
    selector: 'test',
    template: `  
                    Constants: <strong>{{ urlTemplate }}</strong>

              `

})


export class AppComponent{

  constructor(@Inject (Constants) constants: Constants){
    this.urlTemplate = constants.root_dir;
  }

}

Plunker

Community
  • 1
  • 1
Angel Angel
  • 19,670
  • 29
  • 79
  • 105