123 votes

App.settings - la manière angulaire?

Je veux ajouter un App Settings section dans mon Application, où contiennent certains consts et pré valeurs définies.

J'ai déjà lu cette réponse qui utilise OpaqueToken , Mais il est déconseillé dans Angulaire. Cet article explique les différences, mais il n'a pas de fournir un exemple complet , et mes tentatives ont été infructueuses.

Voici ce que j'ai essayé ( je ne sais pas si c'est la bonne façon) :

//ServiceAppSettings.ts

import {InjectionToken, OpaqueToken} from "@angular/core";

const CONFIG = {
  apiUrl: 'http://my.api.com',
  theme: 'suicid-squad',
  title: 'My awesome app'
};
const FEATURE_ENABLED = true;
const API_URL = new InjectionToken<string>('apiUrl');

Et c'est l'élément où je veux utiliser ces consts :

//MainPage.ts

import {...} from '@angular/core'
import {ServiceTest} from "./ServiceTest"

@Component({
  selector: 'my-app',
  template: `
   <span>Hi</span>
  ` ,  providers: [
    {
      provide: ServiceTest,
      useFactory: ( apiUrl) => {
        // create data service
      },
      deps: [

        new Inject(API_URL)
      ]
    }
  ]
})
export class MainPage {


}

Mais il ne fonctionne pas et j'ai des erreurs.

Question:

Comment puis-je consommer "app.les paramètres de" valeurs de l'angle de la sorte?

plunker

NB Sûr que je peux créer Injectables service et le mettre dans le fournisseur de la NgModule , Mais comme je l'ai dit, je veux le faire avec InjectionToken , l'Angulaire.

150voto

tilo Points 6098

Si vous utilisez , il est encore une autre option:

Angulaire de la CLI fournit des fichiers d'environnement en src/environments (par défaut sont environment.ts (dev) et environment.prod.ts (de production)).

Notez que vous devez fournir la configuration des paramètres dans tous environment.* fichiers, par exemple,

de l'environnement.ts:

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

de l'environnement.prod.ts:

export const environment = {
  production: true,
  apiEndpoint: '__your_production_server__'
};

et les utiliser dans votre service (le bon fichier d'environnement est choisi automatiquement):

l'api.service.ts

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

@Injectable()
export class ApiService {     

  public apiRequest(): Observable<MyObject[]> {
    const path = environment.apiEndpoint + `/objects`;
    // ...
  }

// ...
}

Lire plus sur les environnements d'application sur Github (Angulaire de la CLI de la version 6) ou à l' officiel Angulaire guide (version 7).

149voto

Matt Tester Points 1491

Il n'est pas conseillé d'utiliser l' environment.*.ts vos fichiers de l'API de configuration de l'url. Il semble que vous devriez parce que ce mentionne le travail "environnement".

L'utilisation de ce est en fait la compilation de configuration. Si vous souhaitez modifier l'url de l'API, vous aurez besoin de re-construire. C'est quelque chose que vous ne voulez pas avoir à le faire ... il suffit de demander votre environnement de service d'assurance qualité :)

Ce que vous avez besoin est la configuration de l'exécution, c'est à dire l'application des charges de sa configuration lorsqu'il démarre.

Certains autres réponses toucher sur ce, mais la différence est que la configuration de la charge doit être dès que l'application démarre, de sorte qu'il peut être utilisé par un service normal à chaque fois qu'il en a besoin.

Pour mettre en œuvre la configuration de l'exécution:

  1. Ajouter un fichier de configuration JSON à l' /src/assets/ le dossier (si c'est copié sur la compilation)
  2. Créer un AppConfigService de la charge et de distribuer la config
  3. Charger la configuration à l'aide d'un APP_INITIALISER

1. Ajouter un fichier de configuration pour /src/assets

Vous pourriez ajouter à un autre dossier, mais vous auriez besoin de le dire à la CLI que c'est un atout dans l' angular.json. Commencez en utilisant le dossier assets:

{
  "apiBaseUrl": "https://development.local/apiUrl"
}

2. Créer AppConfigService

C'est le service qui sera injecté à chaque fois que vous avez besoin de la valeur de configuration:

@Injectable({
  providedIn: 'root'
})
export class AppConfigService {

  private appConfig: any;

  constructor(private http: HttpClient) { }

  loadAppConfig() {
    return this.http.get('/assets/config.json')
      .toPromise()
      .then(data => {
        this.appConfig = data;
      });
  }

  // This is an example property ... you can make it however you want.
  get apiBaseUrl() {

    if (!this.appConfig) {
      throw Error('Config file not loaded!');
    }

    return this.appConfig.apiBaseUrl;
  }
}

3. Charger la configuration à l'aide d'un APP_INITIALISER

Pour permettre à l' AppConfigService à injecter en toute sécurité, avec la config complètement chargé, nous avons besoin de charger la config à l'application du temps de démarrage. Surtout, l'initialisation d'usine, la fonction doit renvoyer une Promise , de sorte que Angulaires sait attendre jusqu'à ce qu'il finit de se résoudre, avant de terminer de démarrage:

NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      multi: true,
      deps: [AppConfigService],
      useFactory: (appConfigService: AppConfigService) => {
        return () => {
          //Make sure to return a promise!
          return appConfigService.loadAppConfig();
        };
      }
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Maintenant, vous pouvez injecter partout où vous en avez besoin et toutes les config sera prêt à lire:

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {

  apiBaseUrl: string;

  constructor(private appConfigService: AppConfigService) {}

  ngOnInit(): void {
    this.apiBaseUrl = this.appConfigService.apiBaseUrl;
  }

}

Je ne peux pas dire assez fortement, la configuration de l'API url au moment de la compilation de configuration est un anti-modèle. Utiliser la configuration de l'exécution.

68voto

mtpultz Points 403

J'ai trouvé comment faire cela avec InjectionTokens (voir exemple ci-dessous), et si votre projet a été construit à l'aide de l' Angular CLI vous pouvez utiliser les fichiers d'environnement trouvé en /environments statique application wide settings comme une API de point de terminaison, mais en fonction de vos besoins, vous serez plus que probablement en utilisant à la fois depuis l'environnement les fichiers sont juste des littéraux d'objet, alors qu'une injection de configuration à l'aide d' InjectionToken's pouvez utiliser les variables d'environnement et puisque c'est une classe peut avoir de la logique appliquée à configurer sur la base d'autres facteurs dans l'application, comme la demande http initiale de données, un sous-domaine, etc.

L'Injection De Jetons Exemple

/app/app-config.le module.ts

import { NgModule, InjectionToken } from '@angular/core';
import { environment } from '../environments/environment';

export let APP_CONFIG = new InjectionToken<AppConfig>('app.config');

export class AppConfig {
  apiEndpoint: string;
}

export const APP_DI_CONFIG: AppConfig = {
  apiEndpoint: environment.apiEndpoint
};

@NgModule({
  providers: [{
    provide: APP_CONFIG,
    useValue: APP_DI_CONFIG
  }]
})
export class AppConfigModule { }

/app/app.le module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppConfigModule } from './app-config.module';

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

Maintenant, vous pouvez simplement DI dans n'importe quel composant, le service, etc:

/app/core/auth.service.ts

import { Injectable, Inject } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

import { APP_CONFIG, AppConfig } from '../app-config.module';
import { AuthHttp } from 'angular2-jwt';

@Injectable()
export class AuthService {

  constructor(
    private http: Http,
    private router: Router,
    private authHttp: AuthHttp,
    @Inject(APP_CONFIG) private config: AppConfig
  ) { }

  /**
   * Logs a user into the application.
   * @param payload
   */
  public login(payload: { username: string, password: string }) {
    return this.http
      .post(`${this.config.apiEndpoint}/login`, payload)
      .map((response: Response) => {
        const token = response.json().token;
        sessionStorage.setItem('token', token); // TODO: can this be done else where? interceptor
        return this.handleResponse(response); // TODO:  unset token shouldn't return the token to login
      })
      .catch(this.handleError);
  }

  // ...
}

Vous pouvez également vérifier le type de config à l'aide de la exporté AppConfig.

8voto

PJM Points 61

Voici ma solution, charge à partir de .json pour autoriser les modifications sans reconstruire

 import { Injectable, Inject } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Location } from '@angular/common';

@Injectable()
export class ConfigService {

    private config: any;

    constructor(private location: Location, private http: Http) {
    }

    async apiUrl(): Promise<string> {
        let conf = await this.getConfig();
        return Promise.resolve(conf.apiUrl);
    }

    private async getConfig(): Promise<any> {
        if (!this.config) {
            this.config = (await this.http.get(this.location.prepareExternalUrl('/assets/config.json')).toPromise()).json();
        }
        return Promise.resolve(this.config);
    }
}
 

et config.json

 {
    "apiUrl": "http://localhost:3000/api"
}
 

1voto

amku91 Points 507

Voici mes deux solutions pour cela

1. Stocker dans des fichiers json

Il suffit de faire un fichier json et d'obtenir vos composants en $http.get() méthode. Si j'avais besoin de cette très faible alors c'est bon et rapide.

2. Store à l'aide de services de données

Si vous souhaitez les stocker et les utiliser dans toutes les composantes, ou d'avoir un grand usage, alors il est préférable d'utiliser les données de service. Comme ceci :

  1. Il suffit de créer statique dossier à l'intérieur d' src/app le dossier.

  2. Créer un fichier nommé comme fuels.ts en statique dossier. Vous pouvez stocker d'autres fichiers statiques ici aussi. Laissez définir vos données de cette façon. En supposant que vous avoir des carburants de données.

__

export const Fuels {

   Fuel: [
    { "id": 1, "type": "A" },
    { "id": 2, "type": "B" },
    { "id": 3, "type": "C" },
    { "id": 4, "type": "D" },
   ];
   }
  1. Créer un nom de fichier statique.services.ts

__

import { Injectable } from "@angular/core";
import { Fuels } from "./static/fuels";

@Injectable()
export class StaticService {

  constructor() { }

  getFuelData(): Fuels[] {
    return Fuels;
  }
 }`
  1. Maintenant, Vous pouvez les rendre disponibles pour chaque module

il suffit d'importer dans l'application.le module.ts fichier de ce genre et changement de fournisseurs

import { StaticService } from './static.services';

providers: [StaticService]

Maintenant l'utiliser comme StaticService dans n'importe quel module.

C'est Tout.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X