Useful Development

Angular: Creating configurable libraries with angular cli

posted on Jun 21, 2019

When moving a module into a library the using the Angular cli environment settings is no longer an option. This post shows another option for supporting configuration settings in the module. There is already a common pattern for configuring a module using forRoot. With a few changes this can be used to for a library as well.

Getting started

There is a sample for the post available here. If you want to jump to the good bits just clone the repo and skip the rest of this section.

git clone
npm i

To get started create a project, an app (web-app) and a library (normal-lib).

ng n ng-configurable-libs-sample --interactive=false --createApplication=false
cd ng-configurable-libs-sample
ng g application web-app --routing=true
ng g library normal-lib

Make the library configurable

For this sample we want normal-lib to have a setting which will allow the message displayed by the test component to be set by the consuming application. To do this follow the normal forRoot pattern.

Add the following files under the normal-lib/lib folder: normal-lib.config.ts

export interface NormalLibConfig {
  message: string;
import { InjectionToken } from '@angular/core';
import { NormalLibConfig } from './normal-lib-config';

export const NORMAL_LIB_CONFIG = new InjectionToken(
Export NormalLibConfig by adding it to public-api.ts.
export * from './lib/normal-lib-config';
export * from './lib/normal-lib.component';
export * from './lib/normal-lib.module';
export * from './lib/normal-lib.service';
Now we have the config and the injection token so we can provide it and everything in the library can inject the config and use it. The final part is to add the forRoot static function to the library module so the app can set the config when the library is imported. normal-lib.module.ts.
import { ModuleWithProviders, NgModule } from '@angular/core';
import { NormalLibConfig } from './normal-lib-config';
import { NORMAL_LIB_CONFIG } from './normal-lib-config.token';
import { NormalLibComponent } from './normal-lib.component';

  declarations: [NormalLibComponent],
  imports: [
  exports: [NormalLibComponent]
export class NormalLibModule {
  static forRoot(normalLibConfig: NormalLibConfig): ModuleWithProviders {
    return {
      ngModule: NormalLibModule,
      providers: [
          provide: NORMAL_LIB_CONFIG,
          useValue: normalLibConfig

Use the config

In normal-lib.component.ts (the component created by default by ng g library) inject the config and use it.

import { Component, Inject } from '@angular/core';
import { NormalLibConfig } from './normal-lib-config';
import { NORMAL_LIB_CONFIG } from './normal-lib-config.token';

  selector: 'lib-normal-lib',
  template: `
  <h2>Configurable message: {{ message }}</h2>
  styles: []
export class NormalLibComponent {
  message = this.normalLibConfig.message;

  constructor(@Inject(NORMAL_LIB_CONFIG) private normalLibConfig: NormalLibConfig) { }


Finally build the library.

ng build normal-lib

Using the library in the web-app

In the web-app environments files add a message property.

export const environment = {
  message: 'message'
Now import the NormalLibModule and call the forRoot function passing in the environment setting:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NormalLibModule } from 'normal-lib';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

  declarations: [
  imports: [
      message: environment.message
  providers: [],
  bootstrap: [AppComponent]
export class AppModule { }

Now the library module is imported and configured use the NormalLibComponent in the app to check everything is working. app.component.html

<div style="text-align:center">
    ng configurable libs sample

Now if you run the app the message value from environment.ts will be displayed.

ng s


There is one common library type that this approach cannot be used for: lazy loaded feature modules. These require a different approach which will be covered in the next post.