— Code — 2 min read
In this post we'll go through the steps to create and publish an Angular component to the npm package registry.
The first thing you need to publish an Angular component to npm is a npm account, you can sign up here for free.
If you're ready to publish a package to npm you probably already have NodeJS and npm installed, but if not you can install them from https://nodejs.org/en/download/.
Install the Angular CLI globally with command npm i -g @angular/cli
The Angular CLI is the de facto command line tool used to develop, build and test Angular applications. For more info see https://cli.angular.io.
Angular projects are developed within workspaces, so before creating a project you must create a workspace that it will belong to.
Create a new Angular workspace with the command
1ng new <workspace-name> --create-application=false
Then navigate into the workspace folder with the command cd <workspace-name>
The --create-application=false
flag prevents a default Angular application project from being created, because you'll be creating a library project for your component.
The workspace name can be the same as the component project name e.g.
1ng new my-cool-angular-component --create-application=false
Angular library projects are used for developing reusable components and services that can be published as npm packages. They are a special type of project that can't be run on their own and can only be imported and used within other Angular applications.
Create a new library project for your component with the command
1ng generate library <project-name>
(from inside the workspace folder)
1NOTE: check the name of your project or package in npm before creating, if the same name exists it won't work
This will generate a project in your workspace that contains an Angular module with a component and a service.
It's a good idea to check if the package name is already taken on https://www.npmjs.com so you don't have to change it before publishing. Package names must be unique in the npm registry and anyone can publish a package, so it's first in best dressed.
The generated Angular library project comes with a component and a service, so if you only need a component you can delete the service and associated files with the following steps:
projects/<project-name>/src/lib/<project-name>.service.ts
.projects/<project-name>/src/lib/<project-name>.service.spec.ts
.projects/<project-name>/src/public-api.ts
to remove the reference to the deleted service file.Replace the generated Angular component with the custom component that you want to publish to npm.
This is an example code, you make your own package with your code you want.
task-form.component.ts
1import { Component, OnInit } from '@angular/core';2import { FormControl, FormGroup, Validators } from '@angular/forms';3import { Router } from '@angular/router';4import { BsModalRef} from 'ngx-bootstrap/modal';5import { Task } from '../models/Task';6import { TaskManagerService } from '../services/taskmanager.service';78@Component({9 selector: 'app-task-form',10 templateUrl: './task-form.component.html',11 styleUrls: ['./task-form.component.css']12})13export class TaskFormComponent implements OnInit {1415 constructor(public modalRef: BsModalRef,16 private managerService:TaskManagerService,17 private router : Router) { }1819 //Validation20 taskForm = new FormGroup({21 title:new FormControl('',[Validators.required]),22 desciption : new FormControl('',[Validators.required]),23 category : new FormControl ('',[Validators.required]),24 imageUrl : new FormControl ('',[Validators.required]),25 dueDate : new FormControl ('',[Validators.required]),26 priorityLevel : new FormControl ('',[Validators.required])2728 })2930 id?:number;31 get title() { return this.taskForm.get('title'); }32 get desciption() { return this.taskForm.get('desciption'); }33 get category() { return this.taskForm.get('category'); }34 get imageUrl() { return this.taskForm.get('imageUrl'); }35 get dueDate() { return this.taskForm.get('dueDate'); }36 get priorityLevel() { return this.taskForm.get('priorityLevel'); }3738 //get loggedIn UserID and Task Id39 currentUserID!: number;40 latestTaskID!: number;4142 minDate:any = ""4344 ngOnInit(): void45 {46 //get loggedIn UserID47 let userID:string|null = localStorage.getItem('currentUserID')48 this.currentUserID = parseInt(userID == null ? '' : userID)4950 //Get Latest Task Id51 this.managerService.getLatestTaskID(this.currentUserID).subscribe(response => {52 this.latestTaskID = response53 console.log(this.latestTaskID)54 this.id = this.latestTaskID + 155 })5657 this.getDate();58 }5960 // Form Submit61 addTask()62 {63 if(this.taskForm.value.title == '' && this.taskForm.value.desciption == '' && this.taskForm.value.category == '' && this.taskForm.value.imageUrl == '' && this.taskForm.value.dueDate == '')64 {65 alert("Enter Mandatory Fields!")66 }67 else{68 let newTask:Task = new Task (69 this.id!,70 this.taskForm.value.title,71 this.taskForm.value.desciption,72 this.taskForm.value.dueDate,73 this.taskForm.value.priorityLevel,74 this.taskForm.value.category,75 this.taskForm.value.imageUrl)76 console.log(newTask)7778 this.managerService.addNewTask(this.currentUserID, newTask)79 .subscribe(response => {80 console.log(response)81 this.closeModel()82 this.router.navigateByUrl('/cards')83 })84 }8586 }8788 getDate(){89 const date: any = new Date();90 let toDate: any = date.getDate();91 if(toDate<10){92 toDate= "0" + toDate;93 }94 let month: any = date.getMonth() + 1;95 if(month<10){96 month= "0" + month;97 }98 const year = date.getFullYear();99 this.minDate=year + "-" + month + "-" + toDate;100 console.log(this.minDate)101 }102103104// Close Model105 closeModel(){106 this.modalRef.hide()107 }108109}
task-form.component.html
1<div class="modal-content text-color" id="taskModel" role="dialog" aria-labelledby="taskModelForm" aria-hidden="true">2 <div class="modal-header">3 <h6 class="">Add New Task</h6>4 <button type="button" class="close" aria-label="Close" (click)=closeModel() data-dismiss="#modal-content">5 <span aria-hidden="true">×</span>6 </button>7 </div>89 <div class="modal-body">10 <form name="taskForm" [formGroup]="taskForm" (ngSubmit)="addTask()">11 <div class="row">12 <div class="col-12">13 <div class=" form-outline">14 <label for="title" >Task Title </label>15 <input type="text" name="title" id="title" class="form-control" formControlName="title"/>16 </div>17 <mdb-error *ngIf="title && title.invalid && (title.dirty || title.touched)" class="text-danger ml-4 mt-6">Title is Required</mdb-error>18 </div>19 </div>20 <br>21 <div class="row">22 <div class="col-12">23 <div class="form-group">24 <label for="desciption" >Task Description </label>25 <textarea type="text" name="desciption" id="desciption" class="form-control" formControlName="desciption" rows="3"></textarea>26 <mdb-error *ngIf="desciption && desciption.invalid && (desciption.dirty || desciption.touched)" class="text-danger mx-4">Write some content about your task</mdb-error>27 </div>28 </div>29 </div>3031 <div class="row">32 <div class="col-12">33 <div class="form-group">34 <label for="category" >Category </label>35 <input type="text" name="category" id="category" formControlName="category" class="form-control" >36 <mdb-error *ngIf="category && category.invalid && (category.dirty || category.touched)" class="text-danger mx-4">Category should not be empty</mdb-error>37 </div>38 </div>39 </div>4041 <div class="row">42 <div class="col-lg-5">43 <div class="form-outline">44 <label for="dueDate" >Date </label>45 <input type="date" name="dueDate" id="dueDate" formControlName="dueDate" class="form-control" min="{{minDate}}">46 <mdb-error *ngIf="dueDate && dueDate.invalid && (dueDate.dirty || dueDate.touched)" class="text-danger mx-4">Due date should not be empty</mdb-error>47 </div>48 </div>4950 <div class="col-lg-7">51 <div class="form-group">52 <p>Priority</p>53 <div class="form-check form-check-inline">54 <label for="high">55 <input id="high" type="radio" class="form-check-control" formControlName="priorityLevel" value="HIGH" name="priorityLevel">56 High</label>57 </div >58 <div class="form-check form-check-inline">59 <label for="medium" >60 <input id="medium" type="radio" class="form-check-control" formControlName="priorityLevel" value="MEDIUM" name="priorityLevel">61 Medium</label>62 </div>63 <div class="form-check form-check-inline">64 <label for="low">65 <input id="low" type="radio" class="form-check-control" formControlName="priorityLevel" value="LOW" name="priorityLevel">66 Low</label>67 </div>68 </div>69 </div>70 </div>7172 <div class="modal-footer">73 <input class="btn btn-primary" type="submit" value="Save" />74 </div>7576 </form>77 </div>78</div>
Run the command ng build <project-name> --prod
from your workspace folder to build your component, the output files are created in the dist/<project-name>
folder.
The --prod
flag tells the Angular CLI to build the component with the old Angular compiler + runtime to make it compatible with previous versions of Angular (before 9). The new compiler + runtime is called Ivy and the old compiler + runtime is called View Engine.
Run npm login
from the command line and enter the credentials that you used to sign up to npmjs.com in the first step.
Navigate to the project dist folder with the command cd dist/<project-name>
Run the command npm publish
to publish the component the npm.
Now go and check out your new Angular component on the npm website at https://www.npmjs.com/package/<project-name>
. You can also run npm info <project-name>
from the command line to see all the metadata info about your package that's stored on the npm registry.
1NOTE: To update your package in npm you just need to increment the version number in the package.json file and run *npm publish* again.