2016-09-28 153 views
1

我在ASP.NET Core中使用Angular 2.0.0與TypeScript。我的目標是根據服務器端變量在我的應用中創建AppConfig服務。與其他一些答案幫助,我能夠創建下面的代碼:Angular2:將服務器端配置注入服務

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從Chrome的控制檯

Outpup from Chrome console

正如你可以看到由於某種原因創建並注入AppConfig不一樣,並且apiUrl值不會出現在DashboardService。我懷疑這個錯誤是在這裏的某個地方:

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

但我很新的Angular2,不知道如何解決它。你能指出我的問題在哪裏嗎?

+0

聽起來像http://stackoverflow.com/questions/37611549/how-to-pass-pa rameters-rendered-from-backend-to-angular2-bootstrap-method是你正在尋找的。 –

+0

@vebbo您是否根據Günter的反饋設法做到了這一點? – SamJackSon

+0

@SamJackSon是的,通過將appconfig分配給全局「窗口」變量。肯定不是一個優雅的解決方案,但爲我工作。 – vebbo

回答

1

AppConfig提供商@NgModule()陰影供應商傳遞給bootstrapModule()

隨着How to pass parameters rendered from backend to angular2 bootstrap method你應該得到你想要的。

+0

我對這一行有點困惑: ''''''''''''''' – vebbo

+0

而且APP_INITIALIZER不能是基本的。它不被棄用嗎? – vebbo

+0

應該由'@ angular/core'輸出https://angular.io/docs/ts/latest/api/core/index/APP_INITIALIZER-let.html –

0

我最終將對象添加到全局變量。

// =====文件globals.ts

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

// =====文件app.config.ts

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

// =====文件index.html或cshtml

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

// =====文件main.ts

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

// =====文件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

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

看看這個解決方案,以避免全局方法http://plnkr.co/edit/eg1Un1UhduBFGxksRf9P?p=preview – progressdll

0

衛隊使用它加載的配置設置也應努力許諾一個CanActivate類路線。

使用appSettings.service與功能就像一個返回一個承諾

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

,如下列CanActivate後衛:

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

這將確保您的設置時可用構建相應的組件。 (使用APP_INITIALIZER並沒有限制被調用的構造函數,所以我不得不使用這個技術,另外請確保你不導出模塊中出口的所有組件:[])

爲了防止路由和確保設置加載被稱爲構造函數之前,請使用通常的canActivate選項,在路徑路由定義

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

的AppSettings的構造AbcComponent之前應該發生的初始化被調用,這是測試和工程在Angular 2.0.1

+0

也可以使用一個檢查加載設置基於用戶身份驗證true | false或任何其他條件是相關的 – abhijoseph