Angular2: inject server side config into service

前端 未结 3 1600
北荒
北荒 2021-01-27 01:27

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

相关标签:
3条回答
  • 2021-01-27 01:54

    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);
        }
    }
    
    0 讨论(0)
  • 2021-01-27 01:57

    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.

    0 讨论(0)
  • 2021-01-27 02:13

    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

    0 讨论(0)
提交回复
热议问题