1

I need to be able to pass some data (configuration) from angular app to angular library. The requirement is that the configuration needs to be accessible in the decorator of library's NgModule, so I can import some modules conditionally. For example:

@NgModule({
    imports: [
        !envService.data.production ? StoreDevtoolsModule.instrument() : [],
    ]
})
export class LibrarysModule { }

I can't find any documentation on this and there is no clear answer on github in any of the topics I found. Is there any reliable approach for angular 8?

There are couple of similar answer over there on stack overflow, but none of them suits my use case (see: passing environment variables to angular2 library). They all explains how to use forRoot() in order to pass the configration to any service or component of the library. However, I need the configuration in library module's decorator.

Marcin Pevik
  • 163
  • 1
  • 14
  • So you want to include or not to include `StoreDevtoolsModule` depending on the config. Or your question is more theoretical? – igor_c Oct 30 '19 at 16:23
  • Yes, that's the case. The config is passed from outside the library. – Marcin Pevik Oct 30 '19 at 18:01
  • forRoot would work, why don't you want to use it ? – ibenjelloun Oct 31 '19 at 08:10
  • I do. It simply didn't work for me. The imports inside the decorator always resolved before the value was passed from the forRoot factory. Maybe I made some bugs over there but I tried it using different approaches, always with no luck. I assumed it can't done with forRoot()... Am I mistaken? – Marcin Pevik Oct 31 '19 at 09:45
  • @MarcinPevik, you say "The requirement is that the configuration needs to be accessible in the decorator of library's NgModule, so I can import some modules conditionally". My question to you is, why is that your requirement? What is your use case? In the condition when the module is not supposed to get loaded, what are you trying to prevent? My guess is that you are trying to load declarations in one case but not the other. What do you expect to happen when the app is looking for a component/directive but they're not declared? – Sam Herrmann Nov 01 '19 at 12:46
  • @MarcinPevik you should not put store in library. Store should be in your app. – Ravin Singh D Nov 04 '19 at 05:56
  • @SamHerrmann, the good example is to load StoreDevtoolsModule for development environment only. It is not possible to determine prod/dev mode when library is compiled. It needs to be determined by the app that uses my library and passed into the lirbray itself. – Marcin Pevik Nov 04 '19 at 11:54
  • @RavinSinghD, this is new to me! Did you mean that I shouldn't import storeDevTools module or the whole StoreModule in my library? – Marcin Pevik Nov 04 '19 at 11:59
  • you should not import storedevtools as well as store modules to library code. Because your library can be imported to any apps, library components should be work based on input and output. – Ravin Singh D Nov 04 '19 at 12:50
  • @RavinSinghD, this library uses store to manage it's internal data flow. I don't think it might be possible without importing the StoreModule into the library. I could, however, get rid of the StoreDevtoolModule from the library, which will save me couple of KB in bundle size. Thanks for the hint! – Marcin Pevik Nov 04 '19 at 14:18
  • 1
    You could create a service inside a library (aka proxy) which will have a Subject and you can subscribe to it somewhere from your library and call `next` from your app with relevant data – Sergey Nov 05 '19 at 19:26

1 Answers1

0

You can pass external data on bootstrapping.

In main.ts,

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

export function main(myValue: boolean) {
  browserDynamicPlatform().bootstrapModule(wrappedAppModule (myValue));
}

You can wrap your ngModule like this.

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

export function wrappedAppModule (myValue) {
  @NgModule({
    imports: [
        !myValue ? StoreDevtoolsModule.instrument() : [],
    ]
  })
  class AppModule { }

  return AppModule;
}

In your index.html,

<script>
  System.import('app')
    .then(module => module.main(envService.data.production),
       console.error.bind(console)
    );
</script>

Hope this will help.

Thilina Koggalage
  • 1,044
  • 8
  • 16