13

I'm trying again to pass parameters to my application. Since RC5, I have to use ngModule. (this solution: Passing asp.net server parameters to Angular 2 app no longer works since RC5)

How to pass parameters to ngModule?

Here's a plunker to illustrate problem: Plunker

index.html:

<script>
  System.import('app').then(module =>   module.main('This is RIGHT'),
                console.error.bind(console)
            );
</script>

main.ts:

import { browserDynamicPlatform } from '@angular/platform-browser-dynamic';
import { provide } from '@angular/core';
import { AppModule } from './app.module';

export function main(test: string) {

  browserDynamicPlatform().bootstrapModule(AppModule, [{ providers: provide('Test', { useValue: test, }) }]);
}

app.module.ts

import { NgModule, provide }       from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';
import { AppComponent }       from './app.component';

@NgModule({
  imports: [
    BrowserModule
  ],
  declarations: [
    AppComponent
  ],
  providers: [
    provide('Test', { useValue: 'This is WRONG' })
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule {
}
Community
  • 1
  • 1
vidalsasoon
  • 4,365
  • 1
  • 32
  • 40

2 Answers2

17

Update 2

Webpack implementation you can find here Passing server parameters to ngModule with Angular 2 and webpack


Systemjs

Update 1:

We can pass data in the extraProviders property of browserDynamicPlatform function:

main.ts

export function main(test: string) {
  browserDynamicPlatform([{provide: 'Test', useValue: test }])
    .bootstrapModule(AppModule);
}

This way the createAppModule function in app.module.ts is redundant.

Plunker 2.0 Final


Previous version

For RC.5 you can add a method (i.e. createAppModule) in app.module.ts like this:

app.module.ts

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent }  from './app.component';

export function createAppModule(test) {
  @NgModule({
    imports: [BrowserModule],
    providers: [
      { provide: 'Test', useValue: test },
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent]
  })
  class AppModule { }

  return AppModule;
}

This way your main module would be like this:

main.ts

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

import { createAppModule } from './app.module';

export function main(test: string) {
  browserDynamicPlatform().bootstrapModule(createAppModule(test));
}

And your starting point remains the same:

index.html

<script>
  System.import('app')
    .then(module => module.main('This is RIGHT'),
       console.error.bind(console)
    );
</script>

Here is Plunker Example

Community
  • 1
  • 1
yurzui
  • 205,937
  • 32
  • 433
  • 399
  • nice. didn't know we could put attributes inside a function. – vidalsasoon Aug 15 '16 at 11:25
  • Great solution. Is it possible to implement this in production when i use a systemjs builder and it produces one bundled file which i include in the index.html? System.import does not work anymore with this bundled file. I have messed up with systemjs config file for a day without success. – Walaszka Aug 31 '16 at 16:12
  • I use "systemjs builder" with a bundle and this solution didn't cause any issues for me. – vidalsasoon Sep 02 '16 at 13:29
  • Is the systemjs-webpack-plugin what you had used? https://github.com/guybedford/systemjs-webpack-plugin – Gabriel Kohen Sep 21 '16 at 12:20
  • @yurzui how do I send dynamic content to index.html as I mentioned here https://stackoverflow.com/questions/48920091/aspnet-core-new-angular-5-cli-template – k11k2 Feb 22 '18 at 05:17
-1

Please refer to the below work around that works in angular2 2.0.1

Loading server side settings before loading components

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

Community
  • 1
  • 1
abhijoseph
  • 307
  • 1
  • 3
  • 5
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/14049369) – Rob Oct 20 '16 at 21:43
  • I dont mind adding more details, but my intention was not to have duplicate answers – abhijoseph Oct 20 '16 at 22:38
  • I didn't want to pass server params through http. The first answer with 11+ votes answered me perfectly. – vidalsasoon Oct 23 '16 at 18:58