Creating A Simple Library Using Angular CLI 6

Todd Leininger Angular, JavaScript, Single-Page Application, Tutorial 4 Comments

Angular CLI 6 is here! With it, the Angular team has made it much easier to create libraries.

In this article, we show step by step how to create a simple library using Angular CLI 6. Let’s dive right in..

Setup

Let’s get set up to create our library. If you already have Angular CLI 6 installed, skip ahead to the next section.

Install Node.js

To start, we need to install Node.js. You can download the latest LTS installer from Node.js at https://nodejs.org/dist/v8.11.2/node-v8.11.2.pkg. Once the installer is finished, run the following command in the terminal to double check everything worked:

	$ node --version

Install Angular CLI

After Node.js is installed, we can install Angular CLI. In a terminal window, issue the following command:

	$ npm install -g @angular/cli

Once the install is finished, we can issue the following command to make sure we have everything in place:

	$ ng --version

Project

Now that we have the set up finished, we can go ahead and create our new Angular project by issuing the ng new command:

	$ ng new angular-library --prefix al

Now let’s move into our new project with:

	$ cd angular-library

If you are new to version 6 of Angular CLI, then you will notice that the .angular-cli.json file has been replaced with angular.json. New to this version, this file defines your workspace for the project just created. Within you will find two projects are created with the new command. We have our angular-library project and our angular-library-e2e project.

For more information on the angular.json file, visit the Angular Workspace documentation page.

Not only can we now generate multiple applications easily in a new Angular project, but we can also generate our library.

Generate The Library

For this demo, I will use REQ | RES, a hosted REST API that will allow us to quickly get everything up and running. To generate our library for REQ | RES in the project, we will use the ng generate command.

	$ ng generate library reqres --prefix rr

This command has done two things within our project. In the angular.json file we now have reqres project below the angular-libraries-e2e. The second is that in our project we now have a projects folder that contains all the files our library needs to get started.

Create The Models

The next thing we want to do is create a couple of models for our library. For this demo we will just focus on the REQ | RES get list users API. If we go to https://reqres.in/api/users?page=1, we see that the JSON returned will be:

json
{
  "page": 1,
  "per_page": 3,
  "total": 12,
  "total_pages": 4,
  "data": [
    {
      "id": 1,
      "first_name": "George",
      "last_name": "Bluth",
      "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"
    },
    {
      "id": 2,
      "first_name": "Janet",
      "last_name": "Weaver",
      "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"
    },
    {
      "id": 3,
      "first_name": "Emma",
      "last_name": "Wong",
      "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/olegpogodaev/128.jpg"
    }
  ]
}

Let’s create the projects/reqres/src/lib/model folder and our two new classes users and user. Enter the following into the termianl:

	$ ng generate class model/user --project=reqres
	$ ng generate class model/users --project=reqres

Our user model will be:

export class User {
  constructor(
    public id: number,
    public first_name: string,
    public last_name: string,
    public avatar: string
  ) {}
}

Our users model will be:

import { User } from './user';

export class Users {
  constructor(
    public page: number,
    public per_page: number,
    public total: number,
    public total_pages: number,
    public data: User[]
  ) {}
}

Now let’s make our new models available for use. In the projects/reqres/src/public_api.ts file, add the following:

export * from './lib/model/user';
export * from './lib/model/users';

Our entire public_api file should now look as follows:

export * from './lib/reqres.service';
export * from './lib/reqres.component';
export * from './lib/reqres.module';
export * from './lib/model/user';
export * from './lib/model/users';

Create The Service

Angular CLI has already generated the projects/reqres/src/lib/reqres.service.ts file for us so all we need to do is add in our code for calling the API. Let’s open the reqres.service.ts and edit it so the final result is below:

import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Users } from './model/users';

@Injectable({
  providedIn: 'root'
})
export class ReqresService {
  private readonly apiRoot = 'https://reqres.in/api';

  constructor(private httpClient: HttpClient) { }

  getUsers(page: number): Observable<Users> {
    const params = new HttpParams().set('page', String(page));
    return this.httpClient.get<Users>(`${this.apiRoot}/users`, {params: params});
  }
}

This service is pretty straightforward, just a simple ‘get’ to the API. One thing to note is the property providedIn: 'root'. This is new to Angular 6 and it specifies what module the service is to be set up for, in this case, root. This allows for tree shaking to happen for services now.

See Also:  Rethinking REST Practices: An Introduction to GraphQL with AWS AppSync

Create the Components

Now let’s generate the users component for our library. To do this, let’s go back to our terminal and use the CLI to generate our files.

	$ ng generate component users --project=reqres

All we will be doing in this component is generating a list of the users. The final component code will be the following:

import { Component, OnInit, Input } from '@angular/core';
import { ReqresService } from '../../public_api';
import { Users } from '../model/users';

@Component({
  selector: 'rr-user',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.css']
})
export class UsersComponent implements OnInit {
  users: Users;
  @Input() pageNumber: number;

  constructor(private reqresService: ReqresService) { }

  ngOnInit() {
    this.getUsers();
  }

  getUsers(): void {
    this.reqresService.getUsers(this.pageNumber).subscribe(arg => this.users = arg);
  }
}

The HTML for the component is just the following simple list:

<div>
  <ul>
    <li *ngFor="let user of users.data">
      {{user.last_name}}, {{user.first_name}}
    </li>
  </ul>
</div>

Now that we have the component created, let’s make sure our module has everything that it needs.

In the reqres.module.ts file we need to import the CommonModule and the HttpClientModule. The CLI added our declarations for the ReqresComponent and the UsersComponent.

Now we need to add the UsersComponent to the exports so it can be used outside of the module and our library is ready. The final module should look like this:

import { NgModule } from '@angular/core';
import { ReqresComponent } from './reqres.component';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { UsersComponent } from './users/users.component';

@NgModule({
  imports: [CommonModule, HttpClientModule],
  declarations: [ReqresComponent, UsersComponent],
  exports: [UsersComponent]
})
export class ReqresModule { }

Build The Library

Now that we have everything ready for use, we need to build our library. This is as easy as the following command:

	$ ng build reqres

With the build complete, we can go ahead and use it in our root application.

See Also:  State Management with MobX and React

Use The Library

To use the library we first need to import it. In src/app/app.module.ts add the ReqresModule to the imports. The import of the module should look like:

import { ReqresModule } from 'reqres';

The final app.module.ts will be:

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

import { AppComponent } from './app.component';
import { ReqresModule } from 'reqres';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ReqresModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Notice that we are not importing the module using a relative path. We can set this up just like the library was in our node_modules because when the CLI created the library. It also added the following to the tsconfig.json:

"paths": {
      "reqres": [
        "dist/reqres"
      ]
    }

Once the module is published and brought into our application through node_modules, all we will need to do is go back into the tsconfig.json and remove the path.

The last step will be to use our list in our component. Add “ to app.component.html.

Now that we have everything in place lets serve the app by running:

	$ ng serve

Once the server is up and running, going to http://localhost:4200 will display a list of three users in our application that was generated using our library.

Publish The Library

The only thing left to do is to publish our library. If we are publishing to NPM this is issuing a few commands from the terminal. Just remember that to publish to NPM you do need an account. If you don’t have one, just go here to get set up https://www.npmjs.com/signup.

	$ ng build reqres --prod
	$ cd dist/reqres
	$ npm publish

Final Thoughts

And that’s all you need to get your own libraries out for the world!

I hope that this tutorial helped you to have a good idea of how easy it is with Angular CLI 6 to set up your own libraries and to publish them for use. I look forward to seeing what new and exciting modules get created. Please let me know if you have any questions!

Comments 4

  1. I followed your instructions to the letter and the example does not work. One sentence is unclear, however:

    “The last step will be to use our list in our component. Add “ to app.component.html.” Did you mean to put something after the word “Add” that got omitted?

  2. Hi Todd,
    Thanks for this tutorial, it’s very clear explanation.
    I have a question, when running the app it works as expected but press F12 (debug) it shows error context on
    data is undefined. Any idea about this error?

What Do You Think?