Define global constants
In Angular2, you have the following provide definition, which allows you to setup different kinds of dependencies:
provide(token: any, {useClass, useValue, useExisting, useFactory, deps, multi}
Comparing to Angular 1
app.service
in Angular1 is equivalent to useClass
in Angular2.
app.factory
in Angular1 is equivalent to useFactory
in Angular2.
app.constant
and app.value
has been simplified to useValue
with less constraints. i.e. there is no config
block anymore.
app.provider
- There is no equivalent in Angular 2.
Examples
To setup with the root injector:
bootstrap(AppComponent,[provide(API_ENDPOINT, { useValue='http://127.0.0.1:6666/api/' })]);
Or setup with your component's injector:
providers: [provide(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})]
provide
is short hand for:
var injectorValue = Injector.resolveAndCreate([
new Provider(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})
]);
With the injector, getting the value is easy:
var endpoint = injectorValue.get(API_ENDPOINT);
The solution for the configuration provided by the angular team itself can be found here.
Here is all the relevant code:
1) app.config.ts
import { OpaqueToken } from "@angular/core";
export let APP_CONFIG = new OpaqueToken("app.config");
export interface IAppConfig {
apiEndpoint: string;
}
export const AppConfig: IAppConfig = {
apiEndpoint: "http://localhost:15422/api/"
};
2) app.module.ts
import { APP_CONFIG, AppConfig } from './app.config';
@NgModule({
providers: [
{ provide: APP_CONFIG, useValue: AppConfig }
]
})
3) your.service.ts
import { APP_CONFIG, IAppConfig } from './app.config';
@Injectable()
export class YourService {
constructor(@Inject(APP_CONFIG) private config: IAppConfig) {
// You can use config.apiEndpoint now
}
}
Now you can inject the config everywhere without using the string names and with the use of your interface for static checks.
You can of course separate the Interface and the constant further to be able to supply different values in production and development e.g.
Below changes works for me on Angular 2 final version:
export class AppSettings {
public static API_ENDPOINT='http://127.0.0.1:6666/api/';
}
And then in the service:
import {Http} from 'angular2/http';
import {Message} from '../models/message';
import {Injectable} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import {AppSettings} from '../appSettings';
import 'rxjs/add/operator/map';
@Injectable()
export class MessageService {
constructor(private http: Http) { }
getMessages(): Observable<Message[]> {
return this.http.get(AppSettings.API_ENDPOINT+'/messages')
.map(response => response.json())
.map((messages: Object[]) => {
return messages.map(message => this.parseData(message));
});
}
private parseData(data): Message {
return new Message(data);
}
}
Updated for Angular 4+
Now we can simply use environments file which angular provide default if your project is generated via angular-cli.
for example
In your environments folder create following files
environment.prod.ts
environment.qa.ts
environment.dev.ts
and each file can hold related code changes such as:
environment.prod.ts
export const environment = { production: true, apiHost: 'https://api.somedomain.com/prod/v1/', CONSUMER_KEY: 'someReallyStupidTextWhichWeHumansCantRead', codes: [ 'AB', 'AC', 'XYZ' ], };
environment.qa.ts
export const environment = { production: false, apiHost: 'https://api.somedomain.com/qa/v1/', CONSUMER_KEY : 'someReallyStupidTextWhichWeHumansCantRead', codes: [ 'AB', 'AC', 'XYZ' ], };
environment.dev.ts
export const environment = { production: false, apiHost: 'https://api.somedomain.com/dev/v1/', CONSUMER_KEY : 'someReallyStupidTextWhichWeHumansCantRead', codes: [ 'AB', 'AC', 'XYZ' ], };
Use-case in application
You can import environments into any file such as services clientUtilServices.ts
import {environment} from '../../environments/environment';
getHostURL(): string {
return environment.apiHost;
}
Use-case in build
Open your angular cli file .angular-cli.json
and inside "apps": [{...}]
add following code
"apps":[{
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts",
"qa": "environments/environment.qa.ts",
}
}
]
If you want to build for production, run ng build --env=prod
it will read configuration from environment.prod.ts
, same way you can do it for qa
or dev
## Older answer
I have been doing something like below, in my provider:
import {Injectable} from '@angular/core';
@Injectable()
export class ConstantService {
API_ENDPOINT :String;
CONSUMER_KEY : String;
constructor() {
this.API_ENDPOINT = 'https://api.somedomain.com/v1/';
this.CONSUMER_KEY = 'someReallyStupidTextWhichWeHumansCantRead'
}
}
Then i have access to all Constant data at anywhere
import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';
import {ConstantService} from './constant-service'; //This is my Constant Service
@Injectable()
export class ImagesService {
constructor(public http: Http, public ConstantService: ConstantService) {
console.log('Hello ImagesService Provider');
}
callSomeService() {
console.log("API_ENDPOINT: ",this.ConstantService.API_ENDPOINT);
console.log("CONSUMER_KEY: ",this.ConstantService.CONSUMER_KEY);
var url = this.ConstantService.API_ENDPOINT;
return this.http.get(url)
}
}