Angular 2 / Typescriptでグローバル変数を宣言するにはどうすればよいですか?[閉まっている]


164

私はいくつかの変数がどこでもアクセスできるようにしたいと思いAngular 2におけるTypescript言語。これを達成するにはどうすればよいですか?


2
静的変数の場合、サービスを使用する必要はありません。変数をファイルに追加して、必要な場所にインポートします。
Eric Martinez

残念ながら、Angular2は実行時に例外があり、と言っていUncaught ReferenceError: Settings is not definedます。Settingspublic static変数を持つクラスは、エクスポートするように設定されており、使用した場所にインポートされています。
センジェイコブ

私はこの投稿が古く、多くの有効な回答があることを知っています。しかし、エリックが言ったように。宣言し、アプリケーション全体にアクセスできる単純な値の場合は、クラスを作成し、静的プロパティを使用してクラスをエクスポートできます。静的変数は、クラスのインスタンスではなくクラスに関連付けられています。クラスをインポートすると、class.directからプロパティにアクセスできるようになります。
デウェットエリス

回答:


195

以下は、最も単純なソリューションであり、ServiceまたノーObserverです:

グローバル変数をファイルに入れてエクスポートします。

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

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

別のファイルでグローバルを使用するには、importステートメントを使用します。 import * as myGlobals from 'globals';

例:

// 
// ===== 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 (**Updated**)

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";

         ...

        }
    }

ありがとう@ eric-martinez


3
インポート文でエラーが発生しました。使用しなければなりませんでしたimport * as globs from 'globals'
Mike M

13
からのインポートの代わりになぜ「必須」を使用したのですか?
Ayyash、2016年

4
私はexport const代わりに使用しexport varます-あなたは本当にそれらのグローバル変数が変更されないことを確実にしたいのです
Michal Boska

1
このようなインポートはTypeScriptでは無効です。回答を更新してください。正しい次のようになりますimport * as myGlobals from 'globals'
ミック・

7
import * as myGlobals from './path/to/globals';
ティモシーゾーン

89

@supercobraのソリューションも気に入っています。少し改善したいだけです。すべての定数を含むオブジェクトをエクスポートする場合、es6 を使用して、requireを使用せずにモジュールをインポートできます

また、Object.freezeを使用して、プロパティを真の定数にしました。トピックに興味がある場合は、この投稿を読むことができます。

// global.ts

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

インポートを使用してモジュールを参照します。

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

export class HeroService {
    private baseApiUrl = GlobalVariable.BASE_API_URL;

    //... more code
}

これは私にとって最良の解決策です。なぜなら、(1)最小限のコードで最も単純であり、(2)使用するすべての単一のコンポーネントまたは場所にいくつかのdarnサービスを注入する必要がなく、それを行わないからです。 @NgModuleに登録する必要があります。これを行うためになぜAngular 2サービスを作成する必要があるのか​​、私の人生ではわかりませんが、おそらく見落としていることがありますか?私は今、この素晴らしいソリューションを使用していますが、ここで他のより複雑な答えの方が良い理由を教えてください。
FireDragon 2016

8
GlobalVariableは変数ではありません。その定数。
Priya R

@PriyaR LOL、はい、あなたは正しいです。質問の主な目的は、いくつかの値にグローバルにアクセスするための安全な方法を用意することだと思ったので、即興でした。それ以外の場合は、constをvarに変更してもかまいません。変数が取得されます。
Tim Hong、

Object.freezeの欠点は、値が入力されないことです。とにかく、クラスで値をラップすることは、私の観点からはより良いデザインです。したがって、型付きプロパティと真の定数のどちらかを選択する必要があります。
Harps

別のコンポーネントでGlobalVariable.BASE_API_URLを設定する方法
Sunil Chaudhry、2018年

59

共有サービスが最善のアプローチ

export class SharedService {
  globalVar:string;
}

ただし、アプリケーション全体で1つのインスタンスを共有できるように登録する場合は、十分に注意する必要があります。アプリケーションを登録するときに定義する必要があります。

bootstrap(AppComponent, [SharedService]);

ただしproviders、コンポーネントの属性内で再度定義することはできません。

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

それ以外の場合は、サービスの新しいインスタンスがコンポーネントとそのサブコンポーネントに対して作成されます。

Angular2での依存性注入と階層型インジェクターの動作に関するこの質問をご覧ください。

Observableサービスのプロパティを定義して、グローバルプロパティが変更されたときにアプリケーションの一部に通知することもできます。

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

詳細については、この質問を参照してください:


これは違うようですが。@ Rat2000は私たちの答えが間違っていると考えているようです。私は通常、この決定を競合する回答を提供する人以外に任せますが、彼が私たちの回答が間違っていると確信している場合、それは有効だと思います。彼が私の回答へのコメントでリンクしたドキュメントは、それが非推奨であることを述べていますが、私は不利な点はなく、ドキュメントの引数は非常に弱いです。プロバイダーをブートストラップに追加することもよくあります。とにかく、この議論の目的は何でしょうか。そして、何についてHTTP_PROVIDERSも同様ですが、それらも追加されるべきではありませんbootstrap()か?
ギュンターZöchbauer

2
はい、ドキュメントの引数とセクションを読みました。正直なところ、私はそれがなぜドキュメントから落胆したのか本当にわかりません。これは論理的な分割を定義する方法ですか?ブートストラップ時のAngular2コア固有(ルーティングプロバイダー、httpプロバイダー)と、アプリケーションコンポーネントインジェクターのアプリケーション固有のものです。つまり、ルートブート(ブートストラップ時に定義)に対して1つのサブインジェクター(アプリケーション1)しか持てないということです。私は何かを逃していますか?さらに、階層型インジェクターに関するドキュメントでは、サービスプロバイダーはルートインジェクター内で定義されます;-)
Thierry Templier

3
私が見ている唯一の議論は、スコープをできるだけ狭く保つことであり、ルートコンポーネントを使用することは少なくとも理論的には使用するよりも少し狭いということですbootstrap()が、実際にはそれは問題ではありません。それらをリストすることでboostrap()コードが理解しやすくなると思います。コンポーネントには、プロバイダー、ディレクティブ、テンプレートがあります。ここにもグローバルプロバイダーがリストされていないため、これは過負荷になっています。したがって、私は好むbootstrap()
ギュンターZöchbauer

2
そして、どのようにしてそのようなグローバル変数を参照しますか?サービスをブートストラップした後でも、呼び出しalert(globalVar)はエラーになります。
phil294 2016

私はまだこれを試していませんが、次のようなものが必要になります:alert(this.SharedService.globalVar)
trees_are_great 2017年

39

たとえば、Angular 2-共有サービスの実装を参照してください

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

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

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

または個別の値を提供する

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

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

Angular2ベータ7(私は思う)以来、ルートコンポーネント(別名ブートストラップ)にサービスを直接登録しないでください。ただし、アプリケーションで何かをオーバーライドしたい場合は、特定のプロバイダーをそこに注入できます。
Mihai

1
よく分からない。もちろんでサービスを登録できますbootstrap()bootstrap()とルートコンポーネントは2つの異なるものです。あなたが呼び出すとbootstrap(AppComponent, [MyService])、あなたはでサービスを登録boostrap()し、AppComponentルートコンポーネントです。ドキュメントは、ルートコンポーネントにプロバイダー(サービス)を登録することが望ましいとどこかで述べていますproviders: ['MyService']が、私は賛成か反対bootstrap()か、またはルートコンポーネントの議論をまだ見つけていません。
ギュンターZöchbauer

引数は、角度のある2guideセクションのDependency Injection(angular.io/docs/ts/latest/guide/dependency-injection.html)にあります。彼らが言うように、あなたはそれを行うことができますが、それはお勧めできません。このユーザーは、あなたのソリューションが正しいものではないことを明確に魔女に注入するための最良の方法を求めています。同じことが@ThierryTemplierにも当てはまります
Mihai

1
Angularドキュメントからのより重要な引用は、「ブートストラッププロバイダーオプションは、ルーティングサポートなど、Angular自身の事前登録されたサービスを構成およびオーバーライドすることを目的としています」と思います。私はめったに自分でサービスをブートストラップに入れません。そして、ドキュメントが今それを示唆するのを見てうれしいです。
Mark Rajcok 2016年

1
クラスをエクスポートすることを忘れないでください
Demodave '15

15

app / globals.tsに Globalsクラスを作成します。

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

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

あなたのコンポーネントで:

import { Globals } from './globals';

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

:Globalsサービスプロバイダーをコンポーネントの代わりにモジュールに直接追加できます。そのモジュールのすべてのコンポーネントにプロバイダーとして追加する必要はありません。

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

これは、アプリ全体の各コンポーネントにサービスを追加する必要がある場合よりも移植性の高いアプローチを提供するため、最良の答えです。ありがとうございました!
Vidal Quevedo 2017年

5
コードは機能しています。ただし、クラスGlobalsを追加して追加するproviders: [ ... ]と、1つのコンポーネント内の値を変更してから、2番目のコンポーネント内の更新された値を要求できないことに注意してください。注入Globalsするたびに、それは新しいインスタンスです。この動作を変更する場合は 、プロバイダーとして追加しないでくださいGlobals
TimoBähr2017年

ただのメモ、それはそうあるべきです@Injectable()
mast3rd3mon

11

IMHO for Angular2(v2.2.3)の最良の方法は、グローバル変数を含むサービスを追加し、それらをアノテーションproviders内のタグなしでコンポーネントに注入することです@Component。これにより、コンポーネント間で情報を共有できます。

グローバル変数を所有するサンプルサービス:

import { Injectable } from '@angular/core'

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

グローバル変数の値を更新するサンプルコンポーネント:

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

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

  constructor(private someSharedService: SomeSharedService) { }

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

グローバル変数の値を読み取るサンプルコンポーネント:

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

注意providers: [ SomeSharedService ]すべきではない、あなたに追加され@Componentた注釈。このラインインジェクションを追加しないことにより、常に同じインスタンスが提供されますSomeSharedService。行を追加すると、新しく作成されたインスタンスが挿入されます。


:しかし、プロバイダーの行を追加することなく、私はこのようなエラーましたUnhandled Promise rejection: No provider for SomeSharedService
ロッキー

そうですか。providers: [SomeSharedService]親モジュールファイルに追加する必要があります。ありがとう。
ロッキー

これは、モジュールを遅延ロードする場合には機能しません。
lpradhap 2018

9

最善の方法はわかりませんが、コンポーネント内でグローバル変数を定義する最も簡単な方法は、window変数を使用して次のように記述することです。

window.GlobalVariable = "what ever!"

ブートストラップに渡したり、他の場所にインポートしたりする必要はなく、すべてのJSにグローバルにアクセスできます(角度2コンポーネントだけでなく)。


1
私はそれが最悪の方法だと思います。静的変数を使用することで、より複雑ではありませんが、その醜いのいずれか;-)ではありません
ギュンターZöchbauer

2
管理が難しくなることに同意します。でも、プロダクションに入れたいものが見つかるまで、開発に使うのはやめました。静的変数では、使用したい場所に何度でもそれらをインポートする必要があります。また、角度コンポーネントでjqueryを使用して外出先でビューを作成する場合がありました-テンプレートがなく、静的を使用して生成されたDOMにイベントを追加しました変数は痛みです。
Mahdi Jadaliha 2016年

1
さらに、それは静的ではなく、どこからでも値を変更できます!
Mahdi Jadaliha 2016年

1
また、サーバー側のレンダリングを破壊します。ウィンドウやドキュメントを直接操作しないでください。
Erik Honn 2016年

1
同意した。でも個人的には、自分の人生のガイドラインには従いません(それよりも上手くできたなら)
Mahdi Jadaliha、

7

それが私がそれを使う方法です:

global.ts

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

それを使用するには、そのようにインポートするだけです:

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
}

編集:推奨されるように接頭辞「_」を削除。


プライベートプロパティのプレフィックスとして「_」を使用しないでください。github.com/Microsoft/TypeScript/wiki/Coding-guidelines
crh225

4

最善の方法は、オブジェクトを必要な場所にエクスポートおよびインポートすることにより、アプリケーション全体でグローバル変数とオブジェクトを共有することです。

まず、globals.tsなどの新しい.tsファイルを作成し、オブジェクトを宣言します。私はそれを与えたオブジェクトの種類をあなたも使うことができ、あらゆるタイプまたは{}

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

その後、それをインポートします

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

そしてそれを使う

console.log(globalVariables);

3

@supercobraの答えが好きですが、ES6ですでに利用可能なconstキーワードを使用します。

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

export const sep='/';
export const version: string="22.2.2"; 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.