Definisci le costanti globali in Angular 2

In 1.x angular è ansible definire costanti come questo:

angular.module('mainApp.config', []) .constant('API_ENDPOINT', 'http://127.0.0.1:6666/api/') 

Quale sarebbe l’equivalente in Angular2 (con Typescript)? Non voglio ripetere l’url della base API più e più volte in tutti i miei servizi.

Sotto le modifiche funziona per me su Angular 2 versione finale:

 export class AppSettings { public static API_ENDPOINT='http://127.0.0.1:6666/api/'; } 

E poi nel servizio:

 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 { 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); } } 

La soluzione per la configurazione fornita dal team angular stesso può essere trovata qui .

Ecco tutto il codice pertinente:

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 } } 

Ora è ansible iniettare la configurazione ovunque senza utilizzare i nomi delle stringhe e con l’uso dell’interfaccia per i controlli statici.

Ovviamente è ansible separare l’interfaccia e la costante ulteriormente per essere in grado di fornire diversi valori nella produzione e nello sviluppo, ad es

In Angular2, hai la seguente definizione di fornitura , che ti consente di impostare diversi tipi di dipendenze:

 provide(token: any, {useClass, useValue, useExisting, useFactory, deps, multi} 

Confronto con Angolare 1

app.service in Angular1 equivale a useClass in Angular2.

app.factory in Angular1 è equivalente a useFactory in Angular2.

app.constant e app.value sono stati semplificati per useValue con meno vincoli. cioè non c’è più un blocco di config .

app.provider – Non c’è equivalente in Angular 2.

Esempi

Per l’installazione con l’iniettore root:

 bootstrap(AppComponent,[provide(API_ENDPOINT, { useValue='http://127.0.0.1:6666/api/' })]); 

O configura con l’iniettore del tuo componente:

 providers: [provide(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})] 

provide è una breve mano per:

 var injectorValue = Injector.resolveAndCreate([ new Provider(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'}) ]); 

Con l’iniettore, ottenere il valore è facile:

 var endpoint = injectorValue.get(API_ENDPOINT); 

In Angular 4, puoi utilizzare la class di ambiente per mantenere tutti i tuoi globals.

Hai environment.ts e environment.prod.ts per impostazione predefinita.

Per esempio

 export const environment = { production: false, apiUrl: 'http://localhost:8000/api/' }; 

E poi sul tuo servizio:

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

Mentre l’approccio con una class AppSettings con una costante di stringa come ApiEndpoint funziona, non è l’ideale dato che non saremmo in grado di scambiare questo vero ApiEndpoint con altri valori al momento del test dell’unità.

Dobbiamo essere in grado di iniettare questi endpoint di API nei nostri servizi (pensare di iniettare un servizio in un altro servizio). Inoltre, non è necessario creare un’intera class per questo, tutto quello che vogliamo fare è iniettare una stringa nei nostri servizi essendo il nostro ApiEndpoint. Per completare l’ eccellente risposta in pixel , ecco il codice completo su come può essere fatto in Angular 2:

Per prima cosa dobbiamo dire ad Angular come fornire un’istanza del nostro ApiEndpoint quando lo chiediamo nella nostra app (pensateci come registrando una dipendenza):

 bootstrap(AppComponent, [ HTTP_PROVIDERS, provide('ApiEndpoint', {useValue: 'http://127.0.0.1:6666/api/'}) ]); 

E poi nel servizio inseriamo questo ApiEndpoint nel costruttore di servizi e Angular lo fornirà per noi in base alla nostra registrazione di cui sopra:

 import {Http} from 'angular2/http'; import {Message} from '../models/message'; import {Injectable, Inject} from 'angular2/core'; // * We import Inject here import {Observable} from 'rxjs/Observable'; import {AppSettings} from '../appSettings'; import 'rxjs/add/operator/map'; @Injectable() export class MessageService { constructor(private http: Http, @Inject('ApiEndpoint') private apiEndpoint: string) { } getMessages(): Observable { return this.http.get(`${this.apiEndpoint}/messages`) .map(response => response.json()) .map((messages: Object[]) => { return messages.map(message => this.parseData(message)); }); } // the rest of the code... } 

Questa è la mia recente esperienza con questo scenario:

  • @ angular / cli: 1.0.0
  • nodo: 6.10.2
  • @ angular / core: 4.0.0

Ho seguito i documenti ufficiali e aggiornati qui:

https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#dependency-injection-tokens

Sembra che OpaqueToken sia ora deprecato e dobbiamo usare InjectionToken , quindi questi sono i miei file che funzionano come un incantesimo:

app-config.interface.ts

 export interface IAppConfig { STORE_KEY: string; } 

app-config.constants.ts

 import { InjectionToken } from "@angular/core"; import { IAppConfig } from "./app-config.interface"; export const APP_DI_CONFIG: IAppConfig = { STORE_KEY: '[email protected][email protected]' }; export let APP_CONFIG = new InjectionToken< IAppConfig >( 'app.config' ); 

app.module.ts

 import { APP_CONFIG, APP_DI_CONFIG } from "./app-config/app-config.constants"; @NgModule( { declarations: [ ... ], imports: [ ... ], providers: [ ..., { provide: APP_CONFIG, useValue: APP_DI_CONFIG } ], bootstrap: [ ... ] } ) export class AppModule {} 

my-service.service.ts

  constructor( ..., @Inject( APP_CONFIG ) private config: IAppConfig) { console.log("This is the App's Key: ", this.config.STORE_KEY); //> This is the App's Key: [email protected][email protected] } 

Il risultato è pulito e non ci sono avvisi sulla console grazie al recente commento di John Papa in questo numero:

https://github.com/angular/angular-cli/issues/2034

La chiave era implementare in un file diverso l’interfaccia.

Aggiornato per Angular 4+

Ora possiamo semplicemente usare gli ambienti file che forniscono l’impostazione predefinita se il tuo progetto è generato tramite angular-cli.

per esempio

Nella tua cartella ambienti crea i seguenti file

  • environment.prod.ts
  • environment.qa.ts
  • environment.dev.ts

e ogni file può contenere modifiche al codice correlate come:

  • 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' ], }; 

Caso d’uso nell’applicazione

È ansible importare ambienti in qualsiasi file come servizi clientUtilServices.ts

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

 getHostURL(): string { return environment.apiHost; } 

Caso d’uso in costruzione

Apri il tuo file cli angular .angular-cli.json e all’interno di "apps": [{...}] aggiungi il seguente codice

  "apps":[{ "environments": { "dev": "environments/environment.ts", "prod": "environments/environment.prod.ts", "qa": "environments/environment.qa.ts", } } ] 

Se vuoi creare per la produzione, esegui ng build --env=prod leggerà la configurazione da environment.prod.ts , allo stesso modo in cui puoi farlo per qa o dev

## Risposta precedente

Ho fatto qualcosa di simile qui sotto, nel mio 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' } } 

Quindi ho accesso a tutti i dati Costanti ovunque

 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) } } 

Tutte le soluzioni sembrano essere complicate. Sto cercando la soluzione più semplice per questo caso e voglio solo usare le costanti. Le costanti sono semplici. C’è qualcosa che parla contro la seguente soluzione?

app.const.ts

 'use strict'; export const dist = '../path/to/dist/'; 

app.service.ts

 import * as AppConst from '../app.const'; @Injectable() export class AppService { constructor ( ) { console.log('dist path', AppConst.dist ); } } 

Basta usare una costante Typescript

 export var API_ENDPOINT = 'http://127.0.0.1:6666/api/'; 

Puoi usarlo nell’iniettore delle dipendenze usando

 bootstrap(AppComponent, [provide(API_ENDPOINT, {useValue: 'http://127.0.0.1:6666/api/'}), ...]); 

Se si utilizza Webpack , che consiglio, è ansible impostare le costanti per ambienti diversi. Ciò è particolarmente utile quando si hanno valori costanti diversi in base all’ambiente.

Probabilmente avrai più file webpack nella tua directory /config (es. Webpack.dev.js, webpack.prod.js, ecc.). Quindi avrai una custom-typings.d.ts li aggiungerai lì. Ecco il modello generale da seguire in ogni file e un esempio di utilizzo in un componente.

webpack. {env} js

 const API_URL = process.env.API_URL = 'http://localhost:3000/'; const JWT_TOKEN_NAME = "id_token"; ... plugins: [ // NOTE: when adding more properties, make sure you include them in custom-typings.d.ts new DefinePlugin({ 'API_URL': JSON.stringify(API_URL), 'JWT_TOKEN_NAME': JSON.stringify(JWT_TOKEN_NAME) }), 

custom-typings.d.ts

 declare var API_URL: string; declare var JWT_TOKEN_NAME: string; interface GlobalEnvironment { API_URL: string; JWT_TOKEN_NAME: string; } 

Componente

 export class HomeComponent implements OnInit { api_url:string = API_URL; authToken: string = "Bearer " + localStorage.getItem(JWT_TOKEN_NAME)}); } 

L’utilizzo di un file di proprietà che viene generato durante una compilazione è semplice e facile. Questo è l’approccio utilizzato dalla CLI Angolare. Definisci un file di proprietà per ogni ambiente e usa un comando durante la compilazione per determinare quale file viene copiato nella tua app. Quindi importa semplicemente il file delle proprietà da utilizzare.

https://github.com/angular/angular-cli#build-targets-and-environment-files

Un approccio per Angular4 sarebbe la definizione di una costante a livello di modulo:

 const api_endpoint = 'http://127.0.0.1:6666/api/'; @NgModule({ declarations: [AppComponent], bootstrap: [AppComponent], providers: [ MessageService, {provide: 'API_ENDPOINT', useValue: api_endpoint} ] }) export class AppModule { } 

Quindi, al tuo servizio:

 import {Injectable, Inject} from '@angular/core'; @Injectable() export class MessageService { constructor(private http: Http, @Inject('API_ENDPOINT') private api_endpoint: string) { } getMessages(): Observable { return this.http.get(this.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); } } 

Il module.constant di AngularJS non definisce una costante nel senso standard.

Sebbene si regga da solo come meccanismo di registrazione del provider, è meglio compreso nel contesto della relativa funzione module.value ( $provide.value ). La documentazione ufficiale indica chiaramente il caso d’uso:

Registra un servizio di valore con $ injector, ad esempio una stringa, un numero, un array, un object o una funzione. Questo è l’abbreviazione di registrazione di un servizio in cui la proprietà $ get del suo provider è una funzione factory che non accetta argomenti e restituisce il servizio value. Ciò significa anche che non è ansible iniettare altri servizi in un servizio di valore.

Confrontalo con la documentazione per module.constant ( $provide.constant ) che indica anche chiaramente il caso d’uso (enfasi mia):

Registra un servizio costante con $ injector, ad esempio una stringa, un numero, un array, un object o una funzione. Come il valore, non è ansible iniettare altri servizi in una costante. Ma a differenza del valore, una costante può essere iniettata in una funzione di configurazione del modulo (vedi angular.Module) e non può essere sostituita da un decoratore AngularJS .

Pertanto, la funzione constant AngularJS non fornisce una costante nel significato comunemente inteso del termine nel campo.

Detto questo, le restrizioni imposte all’object fornito, insieme alla sua precedente disponibilità tramite $ injector, indicano chiaramente che il nome è utilizzato per analogia.

Se si desidera una costante effettiva in un’applicazione AngularJS, si “fornirebbe” uno nello stesso modo in cui si farebbe in qualsiasi programma JavaScript che sia

 export const π = 3.14159265; 

In Angular 2, è applicabile la stessa tecnica.

Le applicazioni Angular 2 non hanno una fase di configurazione nello stesso senso delle applicazioni AngularJS. Inoltre, non esiste un meccanismo di decoratore di servizi ( AngularJS Decorator ), ma ciò non è particolarmente sorprendente, data la differenza tra loro.

L’esempio di

 angular .module('mainApp.config', []) .constant('API_ENDPOINT', 'http://127.0.0.1:6666/api/'); 

è vagamente arbitrario e leggermente scoraggiante perché $provide.constant viene usato per specificare un object che è incidentalmente anche una costante. Potresti anche aver scritto

 export const apiEndpoint = 'http://127.0.0.1:6666/api/'; 

perché tutti possono cambiare.

Ora l’argomento della testabilità, che deride la costante, è diminuito perché letteralmente non cambia.

Non si prende in giro π.

Ovviamente la semantica specifica dell’applicazione potrebbe essere la modifica dell’endpoint o l’API potrebbe avere un meccanismo di failover non trasparente, quindi sarebbe ragionevole che l’endpoint dell’API cambi in determinate circostanze.

In tal caso, tuttavia, fornire una rappresentazione letterale di stringa di un singolo URL alla funzione constant non avrebbe funzionato.

Un argomento migliore, e probabilmente uno più allineato con il motivo dell’esistenza della funzione AngularJS $provide.constant è che, quando è stato introdotto AngularJS, JavaScript non aveva un concetto di modulo standard . In tal caso, i globali sarebbero usati per condividere valori, mutevoli o immutabili, e l’uso di globals è problematico.

Detto questo, fornire qualcosa di simile attraverso una struttura aumenta l’accoppiamento con tale struttura. Mescola anche la logica specifica angular con la logica che funzionerebbe in qualsiasi altro sistema.

Questo non vuol dire che sia un approccio sbagliato o dannoso, ma personalmente, se voglio una costante in un’applicazione Angular 2, scriverò

 export const π = 3.14159265; 

proprio come avrei dovuto usare AngularJS.

Più cose cambiano …

Puoi creare una class per la tua variabile globale e quindi esportare questa class in questo modo:

 export class CONSTANT { public static message2 = [ { "NAME_REQUIRED": "Name is required" } ] public static message = { "NAME_REQUIRED": "Name is required", } } 

Dopo aver creato ed esportato la tua class CONSTANT , dovresti importare questa class in quella class in cui vuoi usare, come questa:

 import { Component, OnInit } from '@angular/core'; import { CONSTANT } from '../../constants/dash-constant'; @Component({ selector : 'team-component', templateUrl: `../app/modules/dashboard/dashComponents/teamComponents/team.component.html`, }) export class TeamComponent implements OnInit { constructor() { console.log(CONSTANT.message2[0].NAME_REQUIRED); console.log(CONSTANT.message.NAME_REQUIRED); } ngOnInit() { console.log("oninit"); console.log(CONSTANT.message2[0].NAME_REQUIRED); console.log(CONSTANT.message.NAME_REQUIRED); } } 

Puoi usare questo in constructor o ngOnInit(){} , o in qualsiasi metodo di predefine.

Il modo migliore per creare costanti dell’applicazione in Angular 2 è utilizzare i file environment.ts. Il vantaggio di dichiarare tali costanti è che è ansible modificarle in base all’ambiente in quanto può esserci un file di ambiente diverso per ogni ambiente.