Angular is one of the most widely used front-end frameworks. It is used by many companies, individuals and open source developers to build web applications.
Introducing Angular CLI
As many of you would know, building a modern web application using a front-end framework like Angular is no more as simple as developing few html pages and showing them on the browser. To work with modern JavaScript frameworks, you now need an environment to be set on the machine, as well as an environment for the application inside the folder that has to contain the code.
Are you keeping up with new developer technologies? Advance your IT career with our Free Developer magazines covering Angular, React, .NET Core, MVC, Azure and more. Subscribe to this magazine for FREE and download all previous, current and upcoming editions.
The following list shows the required tools to build an Angular application at a higher level:
- The system to be used for development should have Node.js installed on it. Node.js is a server platform that supports building web servers using JavaScript. It is also widely used as a platform to build web applications, as it is very easy to spin up a server and start it instantly on Node.js.
- A Node.js based package manager like npm or yarn is needed to install the libraries to be used in the application.
- The application needs a setup to install a set of required packages containing the library files, tools to compile the TypeScript code, bundle the files together, run unit tests, start a web server and build files to deploy the application. While setting up these tasks has become easier with tools like Grunt, Gulp and Webpack, one still needs to spend time in writing the scripts for these tasks in every new project.
The third point of the above list takes a lot of time and effort.
To reduce this pain, the Angular team created Angular CLI. Angular CLI is a generator that makes the process of building an Angular application easier.
This article will make you comfortable with using Angular CLI by creating a simple Angular application.
Angular CLI Installation
As noted earlier, Node.js has to be installed on the system to be used for development. The installer for Node.js can be downloaded from the official site. The installer adds Node.js and the package manager npm to the system.
Angular CLI is a package to be installed globally using npm. To install it, open a command prompt with administrative privileges and run the following command:
> npm install -g @angular/cli
This command installs the command line tool required to build an application using Angular CLI. To check if the installation is successful, you can check the version of Angular CLI using the following command:
> ng -v
Creating a Project using Angular CLI
Now that our system is ready to develop an Angular application, it would be good to explore the essential features of Angular CLI by building a sample.
Open a command prompt, move to a location where you want to save the project and run the following command:
> ng new SampleApp
This command runs for a few minutes and performs the following tasks:
- Creates a new folder named after the project
- Adds a number of files and folders containing the files to be used to run the application
- Adds a bare minimal Angular application to the folder
- Installs the npm packages
- Enables git in the project
The following screenshot shows the structure of the project on VS Code:
Figure 1 - Project structure
The following listing explains the files and folders shown in figure 1:
- e2e: This folder has to be used to add end-to-end tests. These tests have to be written using protractor. This folder contains some sample tests for the application added by the Angular CLI
- src: This folder contains the source files, spec files, styles, TypeScript configuration files and the index.html file. We will spend most of our time in this folder, as all of the code we write goes into it
- .angular-cli.json: This file contains the configuration to be used by Angular CLI. It includes the HTML file to start the application, the first TypeScript file to be loaded while running the application, paths of the TypeScript configuration files to be used for source files and unit test files
- .editorconfig: This file contains configuration for the editor. The editors used to work on the application read this file and use these settings while creating new files and editing files
- karma.conf.js: This file is the input to the karma test runner. The test runner learns everything about running the tests using the configuration added in this file
- package.json: This file contains the list of dependencies to be installed to develop and deploy the application and a set of scripts to perform operations like starting the application, running tests and generating files for deployment
- protractor.conf.js: This file is used to run end-to-end tests using protractor
- README.md: This file contains documentation of the project in markdown format. By default, it contains the basic commands to be used to work with Angular CLI. It can be modified it to describe the project
- tsconfig.json: This file contains the configuration to be used by the TypeScript compiler. The files tsconfig.app.json and tsconfig.spec.json present in the src folder extend this file to define the configuration to be used to compile the source files and the spec files
- tslint.json: This file contains a set of rules to check quality of the TypeScript code written in the application
Note: npm is the default package manager in Angular CLI. If you are a fan of ‘yarn’ and want to use it, you can ask Angular CLI to globally switch to yarn by running the following command: ng set –global packageManager=yarn
Now the newly created project has just everything you need in an Angular application, you don’t need to set up any tooling by yourself.
A Simpler Setup for an Angular app
While the setup we just saw in Figure 1 is the most comprehensive setup for an Angular application, sometimes the need is just to have a simpler setup for the application.
For example, to write some simple demos, one doesn’t require everything in this setup. Using the ng new command with minimal flag creates a simpler application structure. Following is the command:
> ng new SampleApp –minimal
The following screenshot shows the folder structure of the project created using the above command:
Figure 2 - Minimal Project Structure
On comparing Figure 2 with Figure 1, you will see that the project created with the minimal flag has less number of files in it. The ng new command supports a number of other flags. The following list explains some of the useful flags:
- routing: Adds a routing module to the application
- style: To customize the type of styles to be used in the application. By default, it uses CSS. This flag can be used to change the type of styles to LESS, SCSS or Stylus. The CLI installs the corresponding webpack plugins and generates the Angular CLI config based on the style type specified
- verbose: This flag adds details to the output of Angular CLI commands that will be used in the application
To run the application generated above, run the following command:
> ng serve
This command starts a dev server on port 4200. Open a browser and change the URL to http://localhost:4200 to view the application. The browser would render a page similar to the following:
Figure 3 - Initial page
Understanding the Sample Generated
The page shown on the browser in Figure 3 is generated from the index.html file located in the app folder. The body of this page contains the component app-root, this component is used to bootstrap the application.
<body>
<app-root></app-root>
</body>
The component app-root is defined in the file src/app/app.component.ts. This component doesn’t have much code. The code in this file sets the CSS and template to the component. The following snippet shows the code:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
}
The app-root component is registered in the module AppModule in the file src/app/app.module.ts. As this component is used to start the application, it is set as the bootstrap component in the module. The following snippet shows code of the module:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
The src/main.ts file in the app folder bootstraps the application using AppModule. This file also checks for the environment and runs the application in production mode, if needed. The following snippet shows the code in this file:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
The call to enableProdMode function in the if condition in the above snippet optimizes the code for production build. The resulting code won’t be friendly enough for debugging.
Adding Some Code
Angular CLI provides a number of commands to generate the code. It is a good idea to explore it by adding some code to the application. Before adding any code, let’s add Bootstrap to the application. Run the following command to install bootstrap:
> npm install bootstrap --save
To use it in the application, it has to be configured in the .angular-cli.json file. Open this file and modify the styles property of the application as shown in the following snippet:
"styles": [
"styles.css",
"../node_modules/bootstrap/dist/css/bootstrap.css"
]
As you see, the above snippet adds path of the Bootstrap’s CSS file to the styles of the application. This makes the styles defined in this file available to the application and this file is included in the bundle created for the application.
Let’s add a new component to the application. This component will list a few features of Angular and display a short description when a feature is clicked. The following command generates this component:
> ng generate component angular-features
Angular CLI has shorter versions of these commands as well. The same command can be re-written as:
> ng g c angular-features
This command adds a new folder to the application and adds the component class, CSS file, template file and a unit test file for the component. The following image shows the folder generated:
Figure – 4 Structure of component generated
As every feature will have a few properties, it is better to create an interface to hold the structure of the features. The following command adds the AngularFeature interface to the src/app folder of the application:
> ng g i AngularFeature
Open the file angular-feature.ts and replace the code with the following:
export interface AngularFeature {
name: string;
description: string;
isExpanded: boolean;
}
Open the file angular-features.component.ts and place the following code in this file:
import { Component, OnInit } from '@angular/core';
import { AngularFeature } from '../angular-feature';
@Component({
selector: 'app-angular-features',
templateUrl: './angular-features.component.html',
styleUrls: ['./angular-features.component.css']
})
export class AngularFeaturesComponent implements OnInit {
ngFeatures: AngularFeature[] = [];
constructor() { }
ngOnInit() {
this.ngFeatures = [
{
name: 'Components',
description: `Components are used to create custom HTML elements. The elements are independent and
self sufficient pieces of UI that can be reused in any template. Components also help in making the
template more readable.`,
isExpanded: false
},
{
name: 'Directives',
description: `Directives are used to extend the behavior of the HTML elements. They can be added to
a target HTML element to change the behavior of the element based on the business need.`,
isExpanded: false
},
{
name: 'Pipes',
description: `Pipes are used to format the data before displaying it on the page. Any data bound on the
UI may need some transformation like formatting date, displaying currency symbol or any custom transformation.
All of these transformations can be done using pipes.`,
isExpanded: false
},
{
name: 'Services',
description: `Services are used to handle any non UI logic. They can be injected into any component, directive
or other services where the piece of logic is required.`,
isExpanded: false
}
];
}
}
The component in the above snippet has an array with a few of the features of Angular, a short description of these features and a boolean flag to show or hide the description on the page.
The template of the component has to be modified to show the features in a list. Open the file angular-features.component.html and place the following code in it:
<div>
<ul>
<li *ngFor="let feature of ngFeatures">
<a (click)="feature.isExpanded=!feature.isExpanded">{{feature.name}}</a>
<div *ngIf="feature.isExpanded">{{feature.description}}</div>
</li>
</ul>
</div>
The above snippet a couple of Angular directives and bindings; they are explained below:
- ngFor - It is a directive used to repeat over a list of items in a collection
- ngIf - It is a directive that helps in adding an element to the page or removing an element from the page depending on the condition
- (click): The parentheses around click indicates that this event is bound to a method in the component. The assigned method is called whenever the click event is triggered by the browser on the element
- {{}} (interpolation): The double-curly braced expression is used to bind the values on the page. It is a one-way binding. The binding gets automatically updated whenever there is a change in the value
These concepts will be covered in detail in future posts.
The angular-features component has to be used in the app-root component. Open the app.component.html file and modify it as shown below:
<div style="text-align:center">
<h1>
Welcome to {{title}}!
</h1>
</div>
<h2>Here are some features of Angular: </h2>
<app-angular-features></app-angular-features>
Run the application after saving the changes made. You should see a page similar to the following image:
Figure 5 – Modified application
Click on an entry in the list and you will see the description. Click again on the same entry to hide the description.
Separating data from the component
Now let’s add a service to separate the data from the component. This will make the component focused on what it has to do and also make the data accessible to any other components in the application. Run the following command to generate the service:
> ng g s ngfeatures --module app.module
This command adds a new service and adds it to the module. Without the module flag, the service won’t be added to the module, we would need to register it manually.
Open the file ngfeatures.service.ts and add the following code to it:
import { Injectable } from '@angular/core';
import { AngularFeature } from './angular-feature';
@Injectable()
export class NgfeaturesService {
private ngFeatures: AngularFeature[];
constructor() {
this.ngFeatures = [
{
name: 'Components',
description: `Components are used to create custom HTML elements. The elements are independent and
self sufficient pieces of UI that can be reused in any template. Components also help in making the
template more readable.`,
isExpanded: false
},
{
name: 'Directives',
description: `Directives are used to extend the behavior of the HTML elements. They can be added to
a target HTML element to change the behavior of the element based on the business need.`,
isExpanded: false
},
{
name: 'Pipes',
description: `Pipes are used to format the data before displaying it on the page. Any data bound on the
UI may need some transformation like formatting date, displaying currency symbol or any custom transformation.
All of these transformations can be done using pipes.`,
isExpanded: false
},
{
name: 'Services',
description: `Services are used to handle any non UI logic. They can be injected into any component, directive
or other services where the piece of logic is required.`,
isExpanded: false
}
];
}
public get NgFeatures() : any {
return this.ngFeatures;
}
}
The above service has a private member, ngFeatures. This property holds the array of Angular features. It is assigned with the value in the constructor of the service class. The public property NgFeatures provides read only access to this array to the code blocks outside this service.
The angular-features component has to be modified to use this service. Modify it as shown in the following snippet:
import { Component, OnInit } from '@angular/core';
import { AngularFeature } from '../angular-feature';
import { NgfeaturesService } from '../ngfeatures.service';
@Component({
selector: 'app-angular-features',
templateUrl: './angular-features.component.html',
styleUrls: ['./angular-features.component.css']
})
export class AngularFeaturesComponent implements OnInit {
ngFeatures: AngularFeature[] = [];
constructor(private ngfeaturesSvc: NgfeaturesService) { }
ngOnInit() {
this.ngFeatures = this.ngfeaturesSvc.NgFeatures;
}
}
The application would now produce the same output as it did earlier.
Serving the Angular Application
Till now, the application was executed using the ng serve command. As stated earlier, it is the easiest way and most of the Angular developers use it every day.
Angular CLI provides a few options to control the way the application is served. To open the browser automatically as soon as the command runs, it has to be supplied with the open option. The command is shown below:
> ng serve --open
or
> ng serve -o
Say, someone is running an Angular CLI application and wants to run one more without killing the first one. Then the second application should use a different port, as 4200 is already in use by the first application. A different port number can be passed to the ng serve command using the port option, as shown below:
> ng serve --port 4201
or
> ng serve -p 4201
If an application would run over HTTPS in production, the developers should ideally run it using SSL on local as well. ng serve can be supplied with the ssl option to run it using HTTPS. The following command shows this:
> ng serve --ssl
Checking tslint Errors
The tslint.json file added by the Angular CLI contains a number of rules to validate quality of the TypeScript code written in the application. To evaluate the code against these rules, the following command has to be executed:
> ng lint
This command checks all the source files and the unit test files in the application and lists the errors in the console. Following screenshot shows a sample output:
Figure 6 – tslint errors
Bundling the Angular CLI Application
Once the development is complete, we need to deploy the application. As you would already know, code of the application has to be bundled into a few files to host it on a server. The easiest way to bundle the Angular CLI application is using the following command:
> ng build
This command runs webpack and puts the bundled files in the dist folder in the application. The following screenshot shows the contents of the dist folder:
Figure 7 – Structure of dist folder
This command created a developer friendly version of the bundles. The source maps generated helps in debugging the application on the browser. To create more optimized bundles, the command has to be supplied with the prod option, as shown below:
> ng build --prod
Names of the files generated as a result of the prod option contain a hash in them. Value of the hash changes whenever the contents of the files change. And hence, they help in ignoring the files that are already cached in the browser.
Conclusion
Building an Angular application from scratch is a painful task!
Thankfully, Angular CLI makes this process quite easy with its features and flexibilities. Hope this article got you started with the tool. There is a lot more that can be done with Angular CLI. To explore more options and commands, checkout the wiki.
Download the entire source code of this article (Github).
This article was technically reviewed by Mahesh Sabnis.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Rabi Kiran (a.k.a. Ravi Kiran) is a developer working on Microsoft Technologies at Hyderabad. These days, he is spending his time on JavaScript frameworks like AngularJS, latest updates to JavaScript in ES6 and ES7, Web Components, Node.js and also on several Microsoft technologies including ASP.NET 5, SignalR and C#. He is an active
blogger, an author at
SitePoint and at
DotNetCurry. He is rewarded with Microsoft MVP (Visual Studio and Dev Tools) and DZone MVB awards for his contribution to the community