title: Making dynamically loaded values available in an Angular library
body: <p>I have an Angular application that uses a library. I want to configure the library with some configuration values that are dynamically loaded with a http call by the application (and thus not available at compile time). </p>
  
  <p>What's the best approach for this? Thanks!</p>
  
  <p>I have tried the following methods, but each of them seem to have significant downsides:</p>
  
  <h1>A. LibraryModuleA.forRoot(provider: Provider)</h1>
  
  <p>I created a forRoot method on a module in the lib that takes a provider argument and then used an Injection token to make the configuration injectable in the library. </p>
  
  <p>The downside of this approach is that the module that wants to use the library needs to know a lot in order to get it to work.</p>
  
  <p>Library module:</p>
  
  <pre class="lang-js prettyprint-override"><code>@NgModule({
    // omitted for brevity
  })
  export class LibraryModuleA{
    static forRoot(provider: Provider): ModuleWithProviders {
      return {
        ngModule: LibraryModuleA,
        providers: [provider]
      };
    }
  }
  </code></pre>
  
  <p>Client module that uses the library module:</p>
  
  <pre class="lang-js prettyprint-override"><code>@NgModule({
    imports: [
      LibraryModuleA.forRoot({
        provide: LIBRARY_CONFIGURATION,
        useFactory: (coreState: CoreState): LibraryConfiguration =&gt;
          new LibraryConfiguration(coreState.config1$.value, coreState.config2$.value),
        deps: [CoreState]
      })
    ],
    // omitted for brevity
  </code></pre>
  
  <p>As you can see, the client module needs to create a <code>LibraryConfiguration</code> object and it needs to inject that under the <code>LIBRARY_CONFIGURATION</code> token. This seems like too much responsibility for the client of the library to me.</p>
  
  <h1>B. LibraryModuleA.forRoot(config1: string, config2: string) and a global singleton</h1>
  
  <p>I created a global singleton where I store the configuration values on and I I created a forRoot method on a module in the lib that takes the configuration as a paramter and then use an Injection token to make the configuration injectable in the library.</p>
  
  <p>The downside of this is that I now have a global singleton, which is never a good idea to have and could be the cause of future issues.</p>
  
  <p>Library module:</p>
  
  <pre class="lang-js prettyprint-override"><code>@NgModule({
    // omitted for brevity
  })
  export class LibraryModuleA {
    static forRoot(config1: string, config2: string): ModuleWithProviders {
      return {
        ngModule: LibraryModuleA ,
        providers: [
          {
            provide: LIBRARY_CONFIGURATION,
            useValue: new LibraryConfiguration(config1, config2)
          }
        ]
      };
    }
  </code></pre>
  
  <p>Global state object:</p>
  
  <pre class="lang-js prettyprint-override"><code>class GlobalState {
    config1$: BehaviorSubject&lt;string&gt; = new BehaviorSubject&lt;ApplicationSettings&gt;('');
    config2$: BehaviorSubject&lt;string&gt; = new BehaviorSubject&lt;User&gt;('');
  }
  
  const GLOBAL_STATE: GlobalState = new GlobalState ();
  export default GLOBAL_STATE;
  </code></pre>
  
  <p>Client module that uses the library module:</p>
  
  <pre class="lang-js prettyprint-override"><code>@NgModule({
    imports: [
      LibraryModuleA.forRoot(
        GLOBAL_STATE.config1$.getValue(),
        GLOBAL_STATE.config2$.getValue()
      )
    ],
    // omitted for brevity
  })
  </code></pre>
  
  <h1>C. LibraryConfigurationService</h1>
  
  <p>I created a library configuration service that is available on root level and then I call an init method on this service once after I have retrieved the configuration from the http call.</p>
  
  <p>The downside of this approach is that you must not forget to call the configuration service method if you want to use the library. </p>