Publishing Themeable Angular Libraries

Saad Bin Amjad
Monstar Lab Bangladesh Engineering
6 min readJul 23, 2018
Photo by ian dooley on Unsplash

The greatest strength of developers today comes from the community that they reside in. Across the globe, web development has become faster, more reliable and efficient due to the immense community support.

Creators of open source frameworks are not only looking to solve problems that developers face, but are ensuring that the framework evolves with the ever changing technology standards and business demands. Constant feedbacks in the form of code, user and development experiences, all ensures the growth and maturity of the frameworks.

Growth of Angular

Angular has been growing more than 5x faster than AngularJS did since its original release. In October of 2017, the user base of Angular passed 1 million developers (based on 30 day users to our documentation), and became larger than the user base of AngularJS.

Angular 2+ is one of the classic examples of how framework evolve and adapt so rapidly. The community wanted more from AngularJS, and the creators, along with the community, responded to that call with much success.

We, here at Monstar Lab Bangladesh, worked with Angular 2 CLI based projects from quite an early stage, beta.16 to be exact. Early adaptors like us and the rest of the community is what made the growth of Angular 2+ possible.

Angular Components

The usage of web components in modern web applications are crucial for achieving such fast developments. Angular applications are made up of nested components with unidirectional data flow.

So, when building components for your application, if you want to create some custom components in one of your projects and then reuse it or you want to just contribute it as a library to the open source community, then Angular and some open source packages can provide you with very easy options to get started.

Creating your custom Angular component

Let us try to make a simple time picker component with two themes, red and blue.

First we need to do the usual, i.e create a module in your Angular CLI based application.

import { NgModule } from ‘@angular/core’;import { CommonModule } from ‘@angular/common’;import { TimePickerComponent } from ‘./time-picker.component’;@NgModule({  imports: [    CommonModule  ],  declarations: [TimePickerComponent],  exports: [TimePickerComponent]})export class TimePickerModule { }

Now code in your custom component, the way you deem fit. Here I am skipping all the time-picker component code. Once you are done, make sure you include the custom module in app component.

import { BrowserModule } from ‘@angular/platform-browser’;import { NgModule } from ‘@angular/core’;import { AppComponent } from ‘./app.component’;import { TimePickerModule } from ‘./time-picker/time-picker.module’;@NgModule({  declarations: [    AppComponent  ],  imports: [    BrowserModule,    TimePickerModule  ],  providers: [],  bootstrap: [AppComponent]})export class AppModule { }

Creating different stylings

Let us assume we want to have two themes for the TimePickerComponent, red and blue.

We will use the :host-context to enable these two stylings. For now let us do a simple colored border for the time picker.

:host-context(.red-theme) .wrapper {  position: inherit;  background-color: white;  box-shadow: 3px 3px 1px red;  width: 90%;  height: 16em;}:host-context(.red-theme) .input-box {  font-size: relative;  width: 90%;  border-color: red;}:host-context(.blue-theme) .input-box {  font-size: relative;  width: 90%;  border-color: blue;}:host-context(.blue-theme) .wrapper {  position: inherit;  background-color: white;  box-shadow: 3px 3px 1px blue;  width: 90%;  height: 16em;}.hour span {  font: 16px Monaco, MonoSpace;...

This will ensure that we can get the desired look by simply declaring the theme class in the parent component that uses our custom component. For example:

<div class=”blue-theme”>  <your-component>  </your-component></div>

Including the ng-packagr

If you are closely following Angular and their latest versions, you will know that Angular 6 enables you to create libraries with the help of ng-packagr.

Here I will show you how to use ng-packagr directly into your custom component project, so that you can transpile your custom libraries to Angular Package Format.

There are several articles available online, detailing out as to how to use this packaging library for publishing.

The important steps are as follows:

Install ng-packagr:

npm install ng-packagr — save-dev

Create two files in project directory:

  1. ng-package.json:
{  “$schema”: “./node_modules/ng-packagr/ng-package.schema.json”,  “lib”: {    “entryFile”: “public_api.ts”  }}

2. public_api.ts:

export * from ‘./src/app/time-picker/time-picker.module’;

The public_api file is important, as it states what you want to export for others to import, i.e which modules, services and components you want to expose to developers. Since your component might use a service and you want users to access that service to set defaults, or have more control as to how to use themeable component, this is the file where you mention your exports.

Edit your package.json file, with custom build command. Make sure you have keywords, versioning, and dependencies maintained, so that once you publish it in npm registry, it is well documented.

{  “name”: “ng-time-picker”,  “version”: “0.0.6”,  “license”: “MIT”,  “author”: “saadbinamjad”,  “keywords”: [“Angular”, “Angular2”, “Time Picker”],  “scripts”: {    “ng”: “ng”,    “start”: “ng serve”,    “build”: “ng build”,    “test”: “ng test”,    “lint”: “ng lint”,    “e2e”: “ng e2e”,    “prepackagr”: “ng-packagr -p ng-package.json”,    “packagr”: “npm pack ./dist”  },  “private”: false,  “dependencies”: {},  “devDependencies”: {  “@angular/animations”: “⁵.0.0”,

Create the dist folder using this command:

npm run packagr

This command will first run prepackagr command and then the packagr command. At the end you can see a tar file being generated.

ng-time-picker-0.0.6.tgz

You can take this tar file in any of your desired Angular application root directory and install it locally using the command:

npm install ng-time-picker-0.0.6.tgz — save

Publishing it to npm

You can also publish it to npm so that developers across the world can use your library. To do that, first login in npm from your project directory.

npm login

Publish the package using this command.

npm publish dist

Usage of the created component

To install this module to an external project, follow the procedure:

npm install ng-time-picker — save

And then just import TimePickerModule to your @NgModule, and in your desired html file you can include the component with mentioning the theme.

<div class=”blue-theme”>  <ng-time-picker (notify)=”onNotifyEntry($event)”>

</ng-time-picker>
</div>
The blue themed time picker.
<div class=”red-theme”>  <ng-time-picker (notify)=”onNotifyEntry($event)”>

</ng-time-picker>
</div>
The red themed time picker.

Lessons Learned

To publish a standard library, there are many aspects that one needs to care about, like readable code, meaningful git commits, proper documentation, usage examples etc.

Maintaining dependencies and versioning are crucial for the libraries, and you need to be careful in defining those versions. Host the component in github pages, or firebase so that users can have a look before downloading. These all will help the community to add new features, report or even solve bugs themselves.

You could make this time picker a custom form element so that it can be easily used in a reactive form, and also exposing a config variable to define defaults for the component. Adding such multiple option support, i.e config variables to enable your component’s versatility, so that the user can use it with ease for their desired situation, is something developers should strive for when building libraries.

Try to be very observant as to how the community is adapting and helping the framework to grow. The more you keep reading and start practicing, the better you become. And the more you contribute, the more you learn.

Feel free to share your thoughts via tweets at @saadbinamjad. Till then, happy coding.

--

--

Saad Bin Amjad
Monstar Lab Bangladesh Engineering

Technical Lead at Monstar Lab Bangladesh. Prefers tea over coffee, and coffee over anything else. Loves to speak.