2016-09-28 1 views
1

J'utilise Angular 2.0.0 avec TypeScript dans ASP.NET Core. Mon objectif est de créer un service AppConfig dans mon application, en fonction des variables côté serveur. Avec une aide de quelques autres réponses, j'ai pu créer un code suivant:Angular2: injecter la configuration côté serveur

Index.cshtml

<app> 
    <i class="fa fa-spin fa-5x fa-spinner"></i> 
</app> 

<script> 
    System.import('/app/main').then((m) => { 
     var config = { 
      apiUrl: @options.ApiServerUrl 
     }; 

     m.RunApplication(config); 
    }, console.error.bind(console)); 
</script> 

app.config.ts

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

@Injectable() 
export class AppConfig { 
    apiUrl: string; 
} 

main.ts

import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; 

import { AppModule } from "./app.module"; 
import { AppConfig } from "./app.config"; 

export function RunApplication(config: Object) { 

    var appConfig = new AppConfig(); 
    appConfig.apiUrl = config["apiUrl"]; 

    console.log('Created config: ', appConfig); 

    platformBrowserDynamic() 
     .bootstrapModule(AppModule, [{ providers: [{ provide: AppConfig, useValue: appConfig }] }]) 
     .catch(err => console.error(err)); 
} 

app.module.ts

import { NgModule } from "@angular/core"; 
import { BrowserModule } from "@angular/platform-browser"; 
import { HttpModule } from "@angular/http"; 
import { AppRouting, AppRoutingProviders } from "./app.routes"; 
import { AppConfig } from "./app.config"; 
import { AppComponent } from "./app.component"; 
import { DashboardComponent } from "./dashboard/dashboard.component"; 
import { DashboardService } from "./dashboard/dashboard.service"; 

@NgModule({ 
    declarations: [ 
     AppComponent, 
     DashboardComponent 
    ], 
    imports: [ 
     BrowserModule, 
     HttpModule, 
     AppRouting 
    ], 
    providers: [ 
     AppRoutingProviders, 
     AppConfig, 
     DashboardService 
    ], 
    bootstrap: [AppComponent], 
}) 
export class AppModule { } 

dashboard.service.ts

import { Http } from "@angular/http"; 
import { Injectable } from "@angular/core"; 
import { Observable } from "rxjs/Rx"; 
import "rxjs/add/operator/map"; 
import { AppConfig } from "../app.config"; 

@Injectable() 
export class DashboardService { 

    constructor(private appConfig: AppConfig, private http: Http) { 
     console.log('Injected config: ', appConfig); 
     console.log('Injected apiUrl: ', appConfig.apiUrl); 
    } 
} 

Outpup de console Chrome

Outpup from Chrome console

Comme vous peut voir pour une raison quelconque créé et injecté AppConfig ne sont pas les mêmes, et la valeur apiUrl n'apparaît pas dans DashboardService. Je pense que l'erreur est quelque part ici:

bootstrapModule(AppModule, [{ providers: [{ provide: AppConfig, useValue: appConfig }] }]) 

mais je suis tout à fait nouveau pour Angular2 et ne sais pas comment le résoudre. Pouvez-vous me montrer où est le problème?

+0

Sons comme http://stackoverflow.com/questions/37611549/how-to-pass-pa Rameters-rendu-de-backend-to-angular2-bootstrap-méthode est ce que vous cherchez. –

+0

@vebbo Avez-vous réussi à obtenir ce résultat sur la base des retours de Günter? – SamJackSon

+0

@SamJackSon Oui, en affectant appconfig à une variable globale 'window'. Définitivement pas une solution élégante, mais travaille pour moi. – vebbo

Répondre

1

Votre fournisseur AppConfig dans @NgModule() ombre le fournisseur passé à bootstrapModule()

Avec How to pass parameters rendered from backend to angular2 bootstrap method vous devriez obtenir ce que vous voulez.

+0

Je suis un peu confus à propos de cette ligne: '' useFactory: (config: ConfigService) =>() => config.load() '' Que se passe-t-il ici? – vebbo

+0

De plus APP_INITIALIZER ne peut pas être founbd. N'est-il pas obsolète? – vebbo

+0

Devrait être exporté par '@ angular/core' https://angular.io/docs/ts/latest/api/core/index/APP_INITIALIZER-let.letre –

0

J'ai fini par ajouter un objet aux globals.

// ===== globals.ts File

import { AppConfig } from './app.config'; 
'use strict'; 
export var appConfig: AppConfig; 

// ===== fichier app.config.ts

import { Injectable } from "@angular/core"; 
@Injectable() 
export class AppConfig { 
    entityId: string; 
    formId: string; 
} 

// ===== Fichier index.html ou cshtml

<script> 
    System.import('app').then((m) => { 
     var config = { 
      entityId: '12', 
      formId: '22' 
     }; 
     m.RunApplication(config); 
     }, 
     console.error.bind(console) 
    ); 
</script> 

// ===== main.ts File

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 

import { AppModule } from './app.module'; 
import { AppConfig } from './app.config'; 
import myGlobals = require('./globals'); 

//platformBrowserDynamic().bootstrapModule(AppModule); 

export function RunApplication(config: Object) { 

    var appConfig = new AppConfig(); 
    appConfig.entityId = config["entityId"]; 
    appConfig.formId = config["formId"]; 

    console.log('Created config: ', appConfig, appConfig.entityId, appConfig.formId); 

    myGlobals.appConfig = appConfig; 

    platformBrowserDynamic() 
     .bootstrapModule(AppModule) 
     .catch(err => console.error(err)); 
} 

// ===== fichier app.module. ts

import { AppConfig } from './app.config'; 
import myGlobals = require('./globals'); 
... 

@NgModule({ 
    imports: [ 
     ... 
    ], 
    declarations: [ 
     ... 
    ], 
    providers: [ 
     { 
      provide: AppConfig, 
      useValue: myGlobals.appConfig 
     } 
    ], 
    bootstrap: [AppComponent] 
}) 

// ===== intro.component.ts File

import { AppConfig } from "./app.config"; 
import myGlobals = require('./globals'); 
@Component({ 
    selector: 'my-intro,[my-intro]', 
    templateUrl: '' 
}) 
export class IntroComponent { 
    constructor() { 
     console.log('constructor', 'appConfig', myGlobals.appConfig); 
    } 
} 
+0

Jetez un oeil à cette solution pour éviter l'approche globale http://plnkr.co/edit/eg1Un1UhduBFGxksRf9P?p=preview – progressdll

0

Garde votre itinéraire avec une classe CanActivate en utilisant une promesse qui charge les paramètres de configuration doivent également fonctionner.

Utilisez le appSettings.service avec une fonction comme celle de retour d'une promesse

getAppSettings(): Promise<any> { 
     var observable = this.http.get(this.ApiUrl, { headers: this.headers }) 
      .map((response: Response) => { 
       var res = response.json(); 
       return res; 
      }); 

     observable.subscribe(config => { 
     this.config= config; 
     console.log(this.config) 
     }); 
     return observable.toPromise(); 
    } 

Et la garde CanActivate comme ci-dessous:

import { Injectable } from '@angular/core'; 
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 
import { AppSettingsService } from './appsettings.service'; 

@Injectable() 
export class CanActivateViaAuthGuard implements CanActivate { 

//router: Router 
    constructor(private appSettingsService: AppSettingsService) 
    { 
    } 

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { 
       return this.appSettingsService.getAppSettings().then(() => { 
    return true }); 
    } 
} 

Cela garantira que vos paramètres sont disponibles lorsque le les composants correspondants sont construits. (en utilisant APP_INITIALIZER n'a pas restreint le constructeur étant appelé, donc j'ai dû utiliser cette technique, Aussi s'il vous plaît assurez-vous, vous n'exportons pas tous les composants dans les exportations: [] dans le module)

Pour garder les routes et assurer les réglages sont chargés avant que les constructeurs sont appelés, s'il vous plaît utilisez l'option habituelle canActivate dans le chemin de la définition de l'itinéraire

path: 'abc', 
component: AbcComponent, 
canActivate: [CanActivateViaAuthGuard] 

l'initialisation de appsettings devrait se produire avant que le constructeur pour AbcComponent est appelé, cela est testé et fonctionne dans Angulaire 2.0.1

+0

Peut également utiliser une vérification pour charger les paramètres basés sur l'utilisateur authentifié vrai | faux ou toute autre condition qui est pertinent – abhijoseph