2016-03-22 46 views
95

Desidero che alcune variabili siano accessibili ovunque in un Angular 2 nella lingua Typescript. Qual è il modo migliore per farlo?Qual è il modo migliore per dichiarare una variabile globale in Angular 2/Typescript

+2

Se sono variabili statiche, non è necessario utilizzare i servizi. Basta aggiungere una variabile in qualche file e quindi importarla ovunque ne hai bisogno. –

+0

Sfortunatamente Angular2 ha un'eccezione in fase di esecuzione, che dice "Uncaught ReferenceError: Settings is not defined". La classe 'Impostazioni' con variabili statiche pubbliche è impostata per l'esportazione e importata dove è stata usata. –

+0

So che questo post è vecchio e che ci sono molte risposte valide. Ma come ha detto Eric. Se si tratta di un valore semplice che si desidera dichiarare e accedere a attraverso la propria applicazione, è possibile creare una classe ed esportare la classe con una proprietà statica. Le variabili statiche sono associate a una classe piuttosto che a un'istanza della classe. È possibile importare la classe e sarà in grado di accedere alla proprietà dalla classe.directly. –

risposta

129

Ecco la soluzione più semplice w/o ServiceObserver:

Inserire le variabili globali in un file di un loro esportazione.

// 
// ===== File globals.ts  
// 
'use strict'; 

export const sep='/'; 
export const version: string="22.2.2";  

Per utilizzare variabili globali in un altro file utilizzare un import dichiarazione: import * as myGlobals from './globals';

Esempio:

// 
// ===== File heroes.component.ts  
// 
import {Component, OnInit} from 'angular2/core'; 
import {Router} from 'angular2/router'; 
import {HeroService} from './hero.service'; 
import {HeroDetailComponent} from './hero-detail.component'; 
import {Hero} from './hero'; 
import * as myGlobals from './globals'; //<==== this one 

export class HeroesComponent implements OnInit { 
    public heroes: Hero[]; 
    public selectedHero: Hero; 
    // 
    // 
    // Here we access the global var reference. 
    // 
    public helloString: string="hello " + myGlobals.sep + " there"; 

     ... 

     } 
    } 

Grazie @ eric-martinez

+0

Mi piace questo approccio :) –

+0

Ho risolto il mio problema usando Questo. grazie ... –

+3

Hai ricevuto un errore nella dichiarazione di importazione. dovevo usare 'import * come glob da 'globals'' –

24

Vedi per esempio Angular 2 - Implementation of shared services

@Injectable() 
export class MyGlobals { 
    readonly myConfigValue:string = 'abc'; 
} 

@NgModule({ 
    providers: [MyGlobals], 
    ... 
}) 

class MyComponent { 
    constructor(private myGlobals:MyGlobals) { 
    console.log(myGlobals.myConfigValue); 
    } 
} 

o fornire valori individuali

@NgModule({ 
    providers: [{provide: 'myConfigValue', useValue: 'abc'}], 
    ... 
}) 

class MyComponent { 
    constructor(@Inject('myConfigValue') private myConfigValue:string) { 
    console.log(myConfigValue); 
    } 
} 
+0

Dal momento che Angular2 beta 7 (credo) non dovresti registrare il tuo servizio direttamente nel componente root (aka bootstrap). Tuttavia, è possibile inserire un provider specifico se si desidera eseguire l'override di qualcosa nella propria applicazione. – Mihai

+1

Non sai cosa intendi. Ovviamente puoi registrare un servizio in 'bootstrap()'. 'bootstrap()' e il componente root sono due cose diverse. Quando chiamate 'bootstrap (AppComponent, [MyService])' registrate il servizio in 'boostrap()' e 'AppComponent' è il componente root. I documenti menzionano da qualche parte che è preferibile registrare provider (servizio) nei provider root '' ': ['MyService']' ma non ho trovato alcun argomento a favore o contro 'bootstrap()' o ancora il componente root. –

+0

È possibile trovare il proprio argomento nella sezione angolare 2guide Dependency Injection (https://angular.io/docs/ts/latest/guide/dependency-injection.html). Come si suol dire, puoi farlo ma è SCORAGGIATO. Questo utente sta chiedendo il modo migliore per iniettare qualcosa che la tua soluzione non è corretta. lo stesso vale per @ThierryTemplier – Mihai

43

un servizio condiviso è l'approccio migliore

export class SharedService { 
    globalVar:string; 
} 

ma è necessario essere molto attenti quando registrandolo per essere in grado di condividere una singola istanza per l'intera applicazione. È necessario definire al momento della registrazione la vostra applicazione:

bootstrap(AppComponent, [SharedService]); 

ma non di definire nuovamente entro i providers attributi dei componenti:

@Component({ 
    (...) 
    providers: [ SharedService ], // No 
    (...) 
}) 

In caso contrario verrà creata una nuova istanza del servizio per la componente e sue sotto componenti.

Si può avere uno sguardo a questa domanda per quanto riguarda come la dipendenza di iniezione e iniettori gerarchici lavorano in Angular2:

si può notare che è anche possibile definire Observable proprietà nel servizio ai notifica parti della tua applicazione quando le tue proprietà globali cambiano:

export class SharedService { 
    globalVar:string; 
    globalVarUpdate:Observable<string>; 
    globalVarObserver:Observer; 

    constructor() { 
    this.globalVarUpdate = Observable.create((observer:Observer) => { 
     this.globalVarObserver = observer; 
    }); 
    } 

    updateGlobalVar(newValue:string) { 
    this.globalVar = newValue; 
    this.globalVarObserver.next(this.globalVar); 
    } 
} 

Vedere questa domanda per maggiori dettagli:

+0

Sembra che questo sia diverso però. Sembra @ Rat2000 pensa che la nostra risposta sia sbagliata. Di solito questa decisione viene lasciata agli altri che peaple che fornisce risposte in competizione, ma se è convinto che le nostre risposte sono sbagliate, penso che sia valido. I documenti a cui si è collegato in un commento alla mia risposta indicano che è SCORAGGIATO ma non vedo svantaggi e gli argomenti nei documenti sono piuttosto deboli. È anche abbastanza comune aggiungere provider al bootstrap. Quale sarebbe lo scopo di questo argomento comunque. E per quanto riguarda 'HTTP_PROVIDERS' e simili, dovrebbero anche non essere aggiunti a' bootstrap() '? –

+2

Sì, ho appena letto l'argomento e la sezione nel doc. Onestamente non capisco davvero perché è scoraggiato dal doc. È un modo per definire una divisione logica: cos'è il core specifico di Angular2 (provider di routing, provider http) quando si avvia l'avvio e cosa è specifico dell'applicazione nell'iniettore del componente dell'applicazione. Detto questo, possiamo avere solo un sub iniettore (quello dell'applicazione) per quello di root (definito all'avvio). Mi manca qualcosa? Inoltre nel doc per gli iniettori gerarchici, i service provider sono definiti all'interno dell'iniettore root ;-) –

+3

L'unico argomento che vedo è che mantenere l'ambito il più stretto possibile e utilizzare il componente root è almeno in teoria leggermente più ristretto rispetto all'utilizzo di 'bootstrap() 'ma in pratica non importa. Penso che elencarli in 'boostrap()' renda il codice più facile da capire. Un componente ha provider, direttive, un modello. Trovo questo sovraccarico senza i provider globali elencati qui. Perciò preferisco 'bootstrap()'. –

4

non so il modo migliore , ma il modo più semplice se si desidera definire una variabile globale all'interno di un componente è utilizzare window variabl e per scrivere in questo modo:

window.GlobalVariable = "what ever!"

non c'è bisogno di passare per l'avvio o di importarlo in altri luoghi, ed è globalmente accessibile alle tutti JS (non solo angolari 2 componenti).

+1

Direi che è il modo peggiore. Usare una variabile statica non è più complicato, ma non è poi così brutto ;-) –

+2

Sono d'accordo che rende difficile da gestire. Comunque ho finito per usarli nello sviluppo finché non trovo quello che voglio mettere in produzione. Nella variabile statica devi importarli più e più volte ovunque tu voglia utilizzare, oltre a un caso che stavo producendo la mia vista mentre ero in movimento con jquery in componenti angolari - non c'era un modello e per aggiungere eventi al DOM prodotto usando static variabile è dolore. –

+1

Inoltre, non è statico, è possibile modificare il valore da qualsiasi luogo! –

3

mi piace la risposta di @supercobra, ma vorrei usare la parola chiave const come è nel ES6 sezioni relative a:

// 
// ===== File globals.ts  
// 
'use strict'; 

export const sep='/'; 
export const version: string="22.2.2"; 
63

mi piace la soluzione da @supercobra troppo. Vorrei solo migliorarlo leggermente. Se esporti un oggetto che contiene tutte le costanti, puoi semplicemente usare es6 importare il modulo senza usare richiedere.

Ho anche utilizzato Object.freeze per rendere le proprietà come costanti reali. Se sei interessato all'argomento, puoi leggere questo post.

// global.ts 

export const GlobalVariable = Object.freeze({ 
    BASE_API_URL: 'http://example.com/', 
    //... more of your variables 
}); 

Fare riferimento al modulo utilizzando l'importazione.

//anotherfile.ts that refers to global constants 
import { GlobalVariable } from './path/global'; 

export class HeroService { 
    private baseApiUrl = GlobalVariable.BASE_API_URL; 

    //... more code 
} 
+0

questa per me è la soluzione migliore perché (1) è la più semplice con meno quantità di codice e (2) non richiede di Iniettare qualche servizio darn in ogni singolo componente o luogo in cui si desidera utilizzarlo, né lo fa richiede di registrarlo in @NgModule. Non posso per la vita di me capire perché sarebbe necessario creare un servizio Angular 2 per fare questo, ma forse c'è qualcosa che sto trascurando? Sto usando questa ottima soluzione per ora ma per favore fammi sapere perché le altre risposte più complicate qui sono migliori? – FireDragon

+5

La tua variabile globale non è una variabile. È una costante. –

+0

@PriyaR LOL, sì, hai ragione. Ho pensato che l'obiettivo principale della domanda fosse di avere un modo sicuro per accedere ad alcuni valori a livello globale, così ho improvvisato. Altrimenti, sentiti libero di cambiare const in var, ottieni la tua variabile. –

3

Questo è il modo in cui lo uso:

global.ts

export var server: string = 'http://localhost:4200/'; 
export var var2 : number = 2; 
export var var3 : string = 'var3'; 

da usare solo importare così:

import {Injectable} from "@angular/core"; 
    import {Http, Headers, RequestOptions} from "@angular/http"; 
    import {Observable} from "rxjs/Rx"; 

    import * as glob from "../shared/global"; //<== HERE 

    @Injectable() 
    export class AuthService { 
      private AuhtorizationServer = glob.server 
     } 

CURA: Droped "_" prefissato come raccomandato.

+0

Non utilizzare "_" come prefisso per proprietà private.https: //github.com/Microsoft/TypeScript/wiki/Coding-guidelines – crh225

11

Crea Globali di classe in app/globals.ts:

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

Injectable() 
export class Globals{ 
    VAR1 = 'value1'; 
    VAR2 = 'value2'; 
} 

nel componente:

import { Globals } from './globals'; 

@Component({ 
    selector: 'my-app', 
    providers: [ Globals ], 
    template: `<h1>My Component {{globals.VAR1}}<h1/>` 
}) 
export class AppComponent { 
    constructor(private globals: Globals){ 
    } 
} 

Nota: è possibile aggiungere provider di servizi Globals direttamente al modulo, invece di il componente e non sarà necessario aggiungerlo come fornitore per ogni componente in quel modulo.

@NgModule({ 
    imports: [...], 
    declarations: [...], 
    providers: [ Globals ], 
    bootstrap: [ AppComponent ] 
}) 
export class AppModule { 
} 
+0

Questa è la risposta migliore, poiché offre un approccio più portatile rispetto alla necessità di aggiungere il servizio per ogni componente attraverso l'app. Grazie! –

+2

Il codice funziona. Notate che iniettare la classe 'Globals' anche aggiungendolo a' providers: [...] 'significa che non è possibile modificare un valore all'interno di un componente e quindi chiedere il valore aggiornato all'interno di un secondo componente. Ogni volta che si inietta 'Globals' è una nuova istanza. Se vuoi cambiare questo comportamento, fai semplicemente ** NOT ** add 'Globals' come provider. –

4

Penso che il modo migliore è quello di condividere un oggetto con variabili globali in tutta l'applicazione esportando e importando dove vuoi.

Innanzitutto creare un nuovo Ts di file, ad esempio globals.ts e dichiarare un oggetto. Ho dato un oggetto tipo, ma si potrebbe anche utilizzare un any type or {}

export let globalVariables: Object = { 
version: '1.3.3.7', 
author: '0x1ad2', 
everything: 42 
}; 

Dopo che l'importazione è

import {globalVariables} from "path/to/your/globals.ts" 

e usarlo

console.log(globalVariables); 
7

IMHO per Angular2 (v2.2.3) il modo migliore è aggiungere servizi che contengono la variabile globale e inserirli in componenti senza il tag providers all'interno dello 0 Annotazione. In questo modo puoi condividere le informazioni tra i componenti.

Un servizio di esempio possiede una variabile globale:

import { Injectable } from '@angular/core' 

@Injectable() 
export class SomeSharedService { 
    public globalVar = ''; 
} 

Un componente di esempio aggiornamenti il valore della variabile globale:

import { SomeSharedService } from '../services/index'; 

@Component({ 
    templateUrl: '...' 
}) 
export class UpdatingComponent { 

    constructor(private someSharedService: SomeSharedService) { } 

    updateValue() { 
    this.someSharedService.globalVar = 'updated value'; 
    } 
} 

Un componente di esempio legge il valore della variabile globale:

import { SomeSharedService } from '../services/index'; 

@Component({ 
    templateUrl: '...' 
}) 
export class ReadingComponent { 

    constructor(private someSharedService: SomeSharedService) { } 

    readValue() { 
    let valueReadOut = this.someSharedService.globalVar; 
    // do something with the value read out 
    } 
} 

Note that providers: [ SomeSharedService ] should not be added to your @Component annotation. By not adding this line injection will always give you the same instance of SomeSharedService . If you add the line a freshly created instance is injected.

+0

bella spiegazione bro! –

+0

Ma senza aggiungere la linea di provider, ho ricevuto un errore come questo: 'Rifiuto di Promessa non gestita: nessun provider per SomeSharedService' – Rocky

+0

vedo. Dovrei aggiungere 'providers: [SomeSharedService]' nel file del modulo genitore. Grazie. – Rocky

Problemi correlati