I\'m using Angular 2.0.0 with TypeScript in ASP.NET Core. My goal is to create AppConfig service in my app, based on server-side variables. With a help from few other answers, I
I ended up adding object to globals.
// ===== File globals.ts
import { AppConfig } from './app.config';
'use strict';
export var appConfig: AppConfig;
// ===== File app.config.ts
import { Injectable } from "@angular/core";
@Injectable()
export class AppConfig {
entityId: string;
formId: string;
}
// ===== File index.html or cshtml
<script>
System.import('app').then((m) => {
var config = {
entityId: '12',
formId: '22'
};
m.RunApplication(config);
},
console.error.bind(console)
);
</script>
// ===== File 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));
}
// ===== File app.module.ts
import { AppConfig } from './app.config';
import myGlobals = require('./globals');
...
@NgModule({
imports: [
...
],
declarations: [
...
],
providers: [
{
provide: AppConfig,
useValue: myGlobals.appConfig
}
],
bootstrap: [AppComponent]
})
// ===== File 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);
}
}
Your AppConfig
provider in @NgModule()
shadows the provider passed to bootstrapModule()
With How to pass parameters rendered from backend to angular2 bootstrap method you should get what you want.
Guard your route with a CanActivate class using a Promise which loads the config settings should also work.
Use the appSettings.service with a function just like the one returning a promise
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();
}
And the CanActivate guard as below:
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 });
}
}
This will ensure that your settings are available when the corresponding components are constructed. (using the APP_INITIALIZER did not restrict the constructor being called, so I had to use this technic, Also please make sure, you dont export all the components in the exports:[] in the module)
To guard the routes and ensure settings are loaded before the constructors are called, please use the usual canActivate option in the path for the route definition
path: 'abc',
component: AbcComponent,
canActivate: [CanActivateViaAuthGuard]
The initialization of appsettings should happen before the constructor for AbcComponent is called, this is tested and works in Angular 2.0.1