Angular 6 — Creating and sharing a Library

_ Maxxx_
9 min readMay 10, 2018

--

** Update: I did a talk at Angular Brisbane based on this — here’s a link if you’re interested: https://www.youtube.com/watch?v=G5Fr_8f5HWI

With the release of Angular 6 comes a whole heap of new features and changes, but the one I was looking forward to most was the ability to create libraries.

One of the things I like to do in any development environment is to set up a library of UI controls that can be shared between all of the projects developed by my team.

Pascal Precht said “ …it’s important to realise that we shouldn’t just create custom form controls right away, if there’s a native element (like <input type="number">) that perfectly takes care of the job.” (https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html)

Now, while I bow down before the likes of Pascal, here I have to disagree. Creating your own version of every component is a must, at least for any sizable development shop.

With your own suite of controls (check-boxes, radio buttons, buttons, text inputs, and, of course, date controls!) you can easily tweak them to do exactly what you want, and make the change once to affect all of your applications.

As a real-world example, I worked on a Windows desktop application where we continually found data being written to the database with leading or trailing spaces. It turned out that bored users, while on the phone to customers, would idly tap the space bar to stop the screensaver kicking in!

As we were using our own custom controls, we simply modified them to trim their data. One change in one place, and problem solved across multiple applications!

Up until now, creating a shareable library in Angular wasn’t particularly easy (although using ng-packagr made it much easier than it would otherwise have been).

But with the release of Angular 6 (more importantly, with the release of Angular-CLI 6) it is now so easy to create and consume libraries that you’ll wonder why I bothered to write this!

(The answer is that most of the steps really aren’t documented in any one place).

So let’s write some code!

The Applications

Yes! Applications plural! One of the other new features of Angular is the ability to create multiple apps within a single source structure. Angular refers to these individual apps as ‘Projects’.

For this very simple walk-through, we’ll create the following three projects for a fictitious company, Angular Research Systems.

a) A component library
b) A web app (maybe for our sales staff)
c) A web site for our adoring public.

Getting Started

Make sure you have Angular CLI 6+ installed. See https://github.com/angular/angular-cli if you need help with that.

My output from ng — version

From the command line of your choice, change to the directory within which you want to create the projects and type:

ng new arsprojects -S

This creates a new angular project, in a folder called ‘arsprojects’. The -S option skips the creation of tests. This project will be the ‘container’ inside which all of our ‘real’ projects exist, and so we won’t need tests at this level.

Now open up this folder in your favourite IDE (which is almost certainly VS Code) and you should see something like this…

The file view of our new project

Looking at the file and folder structure, it’s pretty much identical to earlier releases of Angular, and if you were just going to create a single Angular app, then you could just do so in pretty much the same way you’ve been doing it in earlier

versions.

But we’re not going to use anything within the src directory , instead we’re going to create ourselves a library.

Create a Component Library

ng g library ars-components -p ars

The ‘g’ (short for ‘generate’) tells the CLI to generate something, using a schematic called ‘library’.

We’re calling the library ‘ars-components’ because they will be the components used throughout Angular Research Systems.

The -p option tells the CLI to use the prefix ‘ars’ for our selector prefix (so we will refer to our components as <ars-checkbox> for example.

You will see the Angular CLI has created a ‘projects’ directory for us, and inside this projects directory it’s created ars-components with a src directory and what I like to call “a bunch of other files” because we really don’t need to worry too much about them at the moment!

It also creates, by default, a service and component — neither of which we will be using, but let’s not complicate things by deleting them right now.

The other thing this simple CLI command has done is to make changes to the angular.json file in the root of arsprojects.

This file is the replacement for the angular-cli.json file of earlier incarnations.

Take a look at the file, and you will see the CLI has created a section describing our new library project.

"ars-components": {
"root": "projects/ars-components",
"sourceRoot": "projects/ars-components/src",
"projectType": "library",
"prefix": "ars",
"architect": {
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "projects/ars-components/tsconfig.lib.json",
"project": "projects/ars-components/ng-package.json"
},
"configurations": {
"production": {
"project": "projects/ars-components/ng-package.prod.json"
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/ars-components/src/test.ts",
"tsConfig": "projects/ars-components/tsconfig.spec.json",
"karmaConfig": "projects/ars-components/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/ars-components/tsconfig.lib.json",
"projects/ars-components/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "arsprojects"

The CLI has also added a ‘paths’ section to tsconfig.json in the root.

"paths": {
"ars-components": [
"dist/ars-components"
]

It is this simple change to tsconfig.json that will allow our other projects to access our library at development time.

Create a Web Site project

ng g application arswebsite --prefix web

This time we’re generating using the ‘application’ schematic, we’re calling it ‘arswebsite’ and we’re prefixing our selectors with ‘web’.

The CLI creates another directory (called arswebsite) inside our projects directory, inside which is the usual ‘src’ folder which will contain our web site code.

You’ll also see it has created arswebsite-e2e which will contain our end-to-end tests (which I won’t cover in this article).

Create an App project

Creating the app is the same as creating the website project (they’re both just web apps, after all), so you cna probably guess that we’re using

ng g application arsapp --prefix app

So now we have our ‘projects’ top level folder, containing our ars-components library, our arswebsite web site and our arsapp application. Pretty simple, eh?

Let’s check them out…

Up and Running

Just before we get the apps up and running, let’s make three changes:

Edit projects/arsapp/src/app/app.component.html and replace all the source with

<h1>ArsApp</h1>

Edit projects/arswebsite/src/app/app.component.html and replace all the source with

<h1>ArsWeb</h1>

Edit src/app/app.component.html and replace all the source with

<h1>Main Angular App</h1>

Just so we can see what’s happening when we run the various pieces.

ng serve

then open your browser to http://localhost:4200

Open up a new command line and type

ng serve arswebsite — port 4201

and open a new browser tab to http://localhost:4201

Open up a new command line and type

ng serve arsapp — port 4202

and open a new browser tab to http://localhost:4202

You should see all three htmls displayed in your browser windows.

this should be the last time you ever see the ‘Main Angular App’ page — but if you’re anything like me, you’re so used to typing ng serve that you will forget, and see that page instead of the app you actually meant to serve!

Create a Component in our Library

Because we’re going to be working in the library for a while, the easiest thing to do is to change directory to the root of the library’s source.

cd projects/ars-components/src/lib

You can still generate the components without changing directory, but then you will have to specify the path of the component, and also the path to the module the component will be added to.

  • * I just discovered the better way to do this — use the — project option, so no need to cd to the directory, just
ng generate component checkbox — project=ars-components

This will generate us a component called ‘checkbox’

ng g c textinput

This will generate us a component called ‘textinput’

The CLI makes it so easy! We’ve just created two components in our library!

To make these components visible to consumers of our library (i.e. our app and web site) we need to export them.

Change ars-component.module.ts as follows:

exports: [ArsComponentsComponent, CheckboxComponent, TextinputComponent]

Before we can use the components, we need to build the library…

Building the Library

Make sure you’re in the root of arsprojects…

cd yourfolder/arsprojectsng build ars-components

If all is well (and it should be, the CLI has pretty much done everything for us!) after a few seconds you should see a new directory, ‘dist’ created.

You can see that the cli has built and packaged our components library for us and saved the results in the ars-components directory inside the dist directory.

Installing the Library

Before we can use the library in any of our projects, we’ll need to install it…

npm install dist/ars-components

This adds a reference to the package.json file, and adds a link from the node-modules directory to the dist/ars-components directory. Clever, eh? Now when we make a change to our library, we just have to rebuild it — but won’t have to run npm install again (at least during development locally!)

Consuming the Library

To use the components in our library from the arsapp application, make the following changes to arsapp/src/app/app.module.ts

import { ArsComponentsModule } from 'ars-components';

and

imports: [BrowserModule, ArsComponentsModule],

To use the checkbox component in our app, change arsapp/src/app/app.component.html and add

<ars-checkbox></ars-checkbox><ars-textinput></ars-textinput>

To run our arsapp (assuming you killed the earlier ng serve instances)

ng serve arsapp

Browse to http://localhost:4200 and you will see

Our app, using components from our package

Summary

Using the new Angular 6 CLI we’ve created a development environment for all of our Angular applications, sharing a library of components.

Of course, the components as they stand are useless — but hopefully the technique is clear without me making a ‘real’ checkbox and text input.

Things You Will Forget

0. To rebuild the library every time you make a change.

1. ng serve appname I change the html of my base component in root to some annoying message to nag me into not forgetting to serve the correct app!

2. If you clone the app from github, you cannot run npm install, because it will try and install the app-components whichisn’t built yet — and you can’t build the components until you’ve installed the npm packages.
The solution is to edit package.json to remove the reference to the dist/ars-components, delete package-lock.json, then

npm install
ng build ars-components
npm install dist/ars-components

Finally, I leave as an exercise for the reader the task of converting the components to real, functioning components. I’d appreciate your comments, feedback, and suggestions — and if you would be interested in an article making fully-functioning components for our library, let me know!

--

--