0

My goal: get App Config data from static json file and then inject that data into a third party module that I am importing in my AppModule.

I do not want to use the environment files for this purpose, since I need to have single build for deploy to all environments.

Here's what I've tried:

Main.ts (provides the config data before bootstrapping app, so it's available ASAP):

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { APP_CONFIG } from './app/classes/app-config';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

fetch('/assets/config.json')
    .then(response => response.json())
    .then(config => {
        if (environment.production) {
            enableProdMode();
        }

        platformBrowserDynamic([{ provide: APP_CONFIG, useValue: config }])
            .bootstrapModule(AppModule)
            .catch(err => console.error(err))
    })

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Inject } from '@angular/core';
import { AuthModule, AuthConfig } from 'angular-crb-oauth';
import { AppComponent } from './app.component';
...
import { APP_CONFIG } from './classes/app-config';

@NgModule({
    declarations: [
        AppComponent,
        ...
    ],
    imports: [
        ...
        AuthModule.forRoot(this.config.authSettings) // This does not work - 'this.config' is not recognized here
    ],
    providers: [
        ...
    ],
    bootstrap: [AppComponent]
})
export class AppModule {

    constructor(@Inject(APP_CONFIG) private config: APP_CONFIG) {
        console.log('Config - App module', this.config); // This works just fine!
    }

}

What is working: The config is accessible already in AppModule's constructor, and is successfully logged out to the console.

What is not working: The config does not seem to be accessible in the imports array in AppModule.

In Summary: How can I access the config data in the imports array, so I can send it in to AuthModule.forRoot()?

UPDATE

I have tried the solution @AlexK linked to, here: Angular - Use dynamic variables in module definition

The code compiles. But at runtime, the app does not bootstrap and an error is outputted in console.

Here's what I did:

main.ts

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { APP_CONFIG } from './app/classes/app-config';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

fetch('/assets/config.json')
    .then(response => response.json())
    .then(config => {
        if (environment.production) {
            enableProdMode();
        }

        platformBrowserDynamic([{ provide: APP_CONFIG, useValue: config }])
            .bootstrapModule(AppModule.withConfig(config))
            .catch(err => console.error(err))
    })
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Inject } from '@angular/core';
import { AuthModule, AuthConfig } from 'angular-crb-oauth';
import { AppComponent } from './app.component';

@NgModule()
export class AppModule {
    static withConfig(config: any): any {
        return {
            ngModule: AppModule,
            declarations: [
                AppComponent,
                ...
            ],
            imports: [
                ...
                AuthModule.forRoot(config.authSettings)
            ],
            providers: [
                ...
            ],
            bootstrap: [AppComponent]
        };
    }
}

The error output I get in the console:

VM1324 polyfills.js:3657 Unhandled Promise rejection: No NgModule metadata found for '[object Object]'. ; Zone: <root> ; Task: Promise.then ; Value: Error: No NgModule metadata found for '[object Object]'.
    at NgModuleResolver.resolve (VM1326 vendor.js:31821)
    at CompileMetadataResolver.getNgModuleMetadata (VM1326 vendor.js:30950)
    at JitCompiler._loadModules (VM1326 vendor.js:36745)
    at JitCompiler._compileModuleAndComponents (VM1326 vendor.js:36728)
    at JitCompiler.compileModuleAsync (VM1326 vendor.js:36690)
    at CompilerImpl.compileModuleAsync (VM1326 vendor.js:87721)
    at compileNgModuleFactory__PRE_R3__ (VM1326 vendor.js:73772)
    at PlatformRef.bootstrapModule (VM1326 vendor.js:74092)
    at VM1325 main.js:1422
    at ZoneDelegate.invoke (VM1324 polyfills.js:3365) Error: No NgModule metadata found for '[object Object]'.
    at NgModuleResolver.resolve (http://localhost:4200/vendor.js:31821:23)
    at CompileMetadataResolver.getNgModuleMetadata (http://localhost:4200/vendor.js:30950:45)
    at JitCompiler._loadModules (http://localhost:4200/vendor.js:36745:53)
    at JitCompiler._compileModuleAndComponents (http://localhost:4200/vendor.js:36728:36)
    at JitCompiler.compileModuleAsync (http://localhost:4200/vendor.js:36690:37)
    at CompilerImpl.compileModuleAsync (http://localhost:4200/vendor.js:87721:50)
    at compileNgModuleFactory__PRE_R3__ (http://localhost:4200/vendor.js:73772:21)
    at PlatformRef.bootstrapModule (http://localhost:4200/vendor.js:74092:16)
    at http://localhost:4200/main.js:1422:10
    at ZoneDelegate.invoke (http://localhost:4200/polyfills.js:3365:26)
api.onUnhandledError @ VM1324 polyfills.js:3657
handleUnhandledRejection @ VM1324 polyfills.js:3681
api.microtaskDrainDone @ VM1324 polyfills.js:3674
drainMicroTaskQueue @ VM1324 polyfills.js:3572

What could be the problem?

Basya Rosemann
  • 180
  • 2
  • 14
  • Have you tried APP_INITIALIZER as per this answer: https://stackoverflow.com/questions/43193049/app-settings-the-angular-way – Michael Kang Feb 25 '20 at 08:25
  • @pixelbits - yes, it has the same issue. How would I inject the configuration data into the import in AppModule? – Basya Rosemann Feb 25 '20 at 08:46
  • 1
    have you tried this approach: https://stackoverflow.com/questions/54202666/angular-use-dynamic-variables-in-module-definition – Max K Feb 25 '20 at 09:29
  • @MaxK - this looks like it could potentially be a good solution. I have tried implementing, and the code compiles. However at runtime, I get a console error: `Unhandled Promise rejection: No NgModule metadata found for '[object Object]'. ; Zone: ; Task: Promise.then ; Value: Error: No NgModule metadata found for '[object Object]'.` Ideas? I'll update the question with this information. – Basya Rosemann Feb 25 '20 at 11:18

0 Answers0