2016-09-28 128 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