Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Learn Angular Tutorial - Part 2

5.00/5 (10 votes)
21 Sep 2017CPOL15 min read 37.6K   1K  
Create your first Angular project and understand various concepts like Components and modules
This is part 2 of Learn Angular tutorial step by step. In this part, we will create our first Angular project and understand the various concepts like Components and modules.

Articles in the Series

Lab 6: Components and Modules (Running Your First Angular Application)1

Contents

Introduction

In the previous labs, we looked into the basics of Angular, Node, TypeScript, Loaders ad Bundlers. In this lab, we will configure Angular environment and we will try to create the basic Customer screen and make it up and running. So let’s start with the first step downloading Angular framework and configuring typescript compiler.

Step 1: NPM Install to Get Angular Framework

So let’s create a folder called as “Angular” and open the same using VS code. Please refer to Lab 3 on how to use VS code. In case you want to Angular using Visual Studio, you can see this video. If you are eclipse guy, please leave a comment for me below.

Image 1

So as we discussed in Lab 1,t “Node” has “npm” which helps us to get JavaScript open sources. So create a package.json file with the below details and do a “npm install” in the integrated command line of VS code.

TypeScript
{
  "name": "angular-quickstart",
  "version": "1.0.0",
  "license": "ISC",
  "dependencies": {
    "@angular/common": "4.0.0",
    "@angular/compiler": "4.0.0",
    "@angular/core": "4.0.0",
    "@angular/forms": "4.0.0",
    "@angular/http": "4.0.0",
    "@angular/platform-browser": "4.0.0",
    "@angular/platform-browser-dynamic": "4.0.0",
    "@angular/router": "4.0.0",
    "@angular/upgrade": "4.0.0",
    "angular-in-memory-web-api": "0.3.2",
    "bootstrap": "^3.3.6",
    "core-js": "^2.4.1",
    "http-server": "^0.10.0",
    "reflect-metadata": "^0.1.3",
    "rxjs": "^5.4.1",
    "systemjs": "0.19.27",
    "zone.js": "^0.8.4"
  },
  "devDependencies": {
    "@types/core-js": "^0.9.42",
    "typescript": "2.3.4"
  }
}

If all the npm install runs successfully, you should see a node_modules folder in your VS code project directory with the following folder structure.

If you go inside the “Angular” folder, you will see lot of folders like common, http, forms core and so on. Putting in simple words, Angular is MODULAR.

They have developed isolated components for Forms, Http, Core and so on.

Image 2

In AngularJS 1.X, we just had one JS file which had the whole framework. So you drag and drop that single Angular 1.X JS file on HTML page and you are ready with the Angular 1.X environment. But the problem with having the whole framework in one JS files was that you have to include all features, whether you need them or not.

For instance, if you are not using HTTP, still that feature will be loaded. In case of Angular, we have separate discrete components which make Angular awesome.

Image 3

Common Errors During NPM Install

This is the most crucial part of Angular. You can see that in “package.json” file, we have so many dependencies and these dependencies use each other. So if one version is incompatible, the whole NPM command will fail. So below are couple of things you need to take care.

First, keep NPM updated to the latest version or else you can end up with a warning as shown at the side.

AND EVEN IF YOU DO NOT GET THIS WARNING, STILL KEEP THE LATEST NPM VERSION.

Image 4

To get the latest NPM version, you need to use “npm install -g npm”. This command will update NPM itself.

Also, you can get the below error which shows incompatibility between modules. For example, in the below figure, it says “For Angular 4.0, you will need Zone.js which is greater than 0.8.4 version.

Image 5

So go to your project.json, fix the version number, DELETE node_modules folder and do a NPM again.

Image 6

Errors of version mismatch can be huge as shown in the below figure. Sometimes fixing “package.json” can be more painful and iterative. When you do these iterations, please ensure you delete “node_modules” folder so that you are not referring to old versions.

Image 7

You can also get an error as shown below “ERR nottarget”. This error says that the particular version number is not found. Use “npm view packagename version” command to get the latest version and update your package accordingly.

Image 8

Step 2: Typescript Configuration tsconfig.json

Also in the same folder, we need to create tsconfig.json which defines how typescript will compile. Do not worry about what settings are there in it. We will explain as we go ahead. Remember do not OVERLEARN. For now, just note that the below file defines how TSC will compile.

TypeScript
{
  "compilerOptions": {
    "target": "es5",//defines what sort of code ts generates, 
                                   //es5 because it's what most browsers 
                                   //currently UNDERSTAND.
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true, //for Angular to be able to use metadata,
                                   //we specify in our components.
    "experimentalDecorators": true,//angular needs decorators like 
                                   //@Component, @Injectable, etc.
    "removeComments": false,
    "noImplicitAny": false,
    "noStrictGenericChecks": true,
    "lib": ["es2016", "dom"] 
  }
}

Step 3: Configuring SystemJS Module Loader

SystemJS file defines configuration of how SystemJS will load the frameworks. So this file puts it in the same folder with the name “systemjs.config.js”. The name should be EXACTLY “systemjs.config.js” because systemJS looks with that name.

TypeScript
(function (global) {
    System.config({
        paths: {
            // paths serve as alias
            'npm:': '../node_modules/'
        },
        // map tells the System loader where to look for things
        map: {
            // our app is within the app folder
            app: 'startup',
            // angular bundles
            '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
            '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
            '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
            '@angular/platform-browser': 
            'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
            '@angular/platform-browser-dynamic': 
            'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
            '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
            '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
            '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
            'lodash':'node_modules/lodash',
            // other libraries
            'rxjs': 'npm:rxjs',
            'angular-in-memory-web-api': 
            'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
            'moment': 'npm:moment',
            // ag libraries
            'ag-grid-ng2': '../node_modules/ag-grid-ng2',
            'ag-grid': '../node_modules/ag-grid',
	'jquery': '../node_modules/jquery/dist/jquery.js',
            'ng2-auto-complete': '../node_modules/ng2-auto-complete/dist'
        },
        // packages tells the System loader how to load when no filename and/or no extension
        packages: {
            app: {
                main: '../Startup/Startup.js',
                defaultExtension: 'js'
            },
            rxjs: {
                defaultExtension: 'js'
            },
            'angular-in-memory-web-api': {
                main: './index.js',
                defaultExtension: 'js'
            },
            'lodash': { main: './index.js', defaultExtension: 'js' },
            moment: {
                defaultExtension: 'js'
            },
            'ag-grid-ng2': {
                defaultExtension: "js"
            },
            'ag-grid': {
                defaultExtension: "js"
            },
            'ng2-auto-complete': {
                main: 'ng2-auto-complete.umd.js', defaultExtension: 'js'
            }
        }
    });
})(this);

Understanding Angular Component and Module Architecture

As we said in the previous section, the whole goal of Angular is binding the model and the view. In Angular, the binding code is officially termed as “Component”. So henceforth, we will use the word “Component” for the binding code.

In enterprise projects, you can have lot of components. With many components, it can become very difficult to handle the project. So you can group components logically into modules.

Image 9

So henceforth, I will be using two terms:

  • Components: This will have the binding logic to bind the UI and the model.
  • Modules: This will logically group components.

Step 4: Following MVW Step by Step – Creating the Folders

Before we start coding, let's visualize the steps of coding. As we have mentioned, Angular is a binding framework. It follows MVW architecture. It binds HTML UI with the JavaScript code (model).

So if we visualize it will look something as shown in the image below. So let’s move from right to left. So let’s do the coding in the following sequence:

  1. Create the model.
  2. Create the Component.
  3. Create the module.
  4. Create the HTML UI.

Image 10

So let’s first create four folders in our project:

  • View folder: This folder will contain the HTML UI.
  • Model folder: This folder will have the main business typescript classes.
  • Component folder: This folder will have the binding code which binds the HTML UI and Model.
  • Module: This folder will have code which will logically group the components.

Image 11

In order to create a folder in VS code, you can use the “New folder” icon or you can right click and also create a folder.

Image 12

Step 5: Creating the Model

Image 13

A model is nothing but a class with properties and behavior. So let us first create the customer model with three properties, “CustomerName”, “CustomerCode” and “CustomerAmount”.

So right click on the “Model” folder and add a new file “Customer.ts”. Keep the extension of this file as “.ts” as it’s a typescript file.

While compiling, the typescript command identifies only files with the extension “.ts”.

In the “Customer.ts”, let’s create a “Customer” class with three properties. In this book, we will not be going through the basics of typescript, please do go through this 1 hour training video of typescript which explains typescript in more detail.

TypeScript
export class Customer {
    CustomerName: string = "";
    CustomerCode: string = "";
    CustomerAmount: number = 0;
}

Step 6: Creating the Component

Image 14

The next thing we need to code is the binding code. Binding code in Angular is represented by something termed as “COMPONENTS”. Angular components has the logic which helps to bind the UI with the model.

So right click on the component folder and add “CustomerComponent.ts” file as shown in the figure at the left.

In the component, we need to import two things - the Angular core and our Customer model. Please note “import” is a typescript syntax and not JavaScript. So in case you are not following the code, please see this Learn TypeScript in 1 hour video before moving ahead.

TypeScript
import {Customer} from '../Model/Customer'
import {Component} from "@angular/core"

The first line imports the “Customer” class in to the “CustomerComponent.ts”. This import is only possible because we have written “export” in “Customer.ts” file. The import and export generate code which follows CommonJs, AMD or UMD specifications. In case you are new to these specifications, please see this CommonJs video which explains the protocol in more detail.

TypeScript
import {Customer} from '../Model/Customer'
Image 15

Let’s try to understand how “Customer” component is located. If you see it’s using a relative path. In the import, it says “../Model/Customer”.

The “../” says go one folder up. So we are currently in the “Component” folder, so with “../”, it travels to the root and from that point it makes entry in to the “Model” folder.

The next import command imports Angular core components. In this, we have not given any relative path using “../” etc. So how does typescript locate the Angular core components?

TypeScript
import {Component} from "@angular/core"

If you remember, we had used node to load Angular and node loads the JS files in the “node_modules” folder. So how does typescript compiler automatically know that it has to load the Angular components from “node_modules” folder.
Typescript compiler uses the configuration from “tsconfig.json” file. In the configuration, we have one property termed as “moduleResolution". It has two values:

  • Classic: In this mode, typescript relies on “./” and “../” to locate folders.
  • Node: In this mode, typescript first tries to locate components in “node_modules” folder and if not found, then follows the “../” convention to traverse to the folders.

In our tsconfig.json, we have defined the mode as “node”. This makes typescript hunt modules automatically in “node_modules” folder. That makes the “import” of Angular components work.

TypeScript
{
 {
  ....
  ....
    "moduleResolution": "node",
 ....
 ....
  }
}

So now that both the import statements are applied, let us create the “CustomerComponent” and from that, let’s expose “Customer” object to the UI with the object name “CurrentCustomer”.

TypeScript
export class CustomerComponent {
    CurrentCustomer:Customer = new Customer();
}

As we said previously, component connects / binds the model to the HTML UI. So there should be some code which tells that “CustomerComponent” is bounded with HTML UI. That’s done by something termed as “Component MetaData Attribute”. A component metadata attribute starts with “@Component” which has a “templateUrl” property which specifies the HTML UI with which the component class is tied up with.

TypeScript
@Component({
    selector: "customer-ui",
    templateUrl: "../UI/Customer.html"
})

This attribute is then decorated on the top of the component. Below goes the full code.

TypeScript
@Component({
    selector: "customer-ui",
    templateUrl: "../UI/Customer.html"
})
export class CustomerComponent {
    CurrentCustomer:Customer = new Customer();
}




Image 16

Put in simple words, binding code is nothing but a simple typescript class which decorated by the “@Component” attribute which dictates that this typescript class is binded with which UI.

Below goes the full code of the Angular component.

TypeScript
// Import statements
import {Component} from "@angular/core"
import {Customer} from '../Model/Customer'

// Attribute metadata
@Component({
    selector: "customer-ui",
    templateUrl: "../UI/Customer.html"
})
// Customer component class exposing the customer model
export class CustomerComponent {
    CurrentCustomer:Customer = new Customer();
}

Step 7: Creating the Customer HTML UI – Directives and Interpolation

Now from the “CustomerComponent”, “Customer” is exposed via the “CurrentCustomer” object to UI. So in the HTML UI, we need to refer this object while binding.

In the HTML UI, the object is binded by using “Directives”. Directives are tags which direct how to bind with the UI.

For instance, if we want to bind “CustomerName” with HTML textbox code goes something as shown below:

  • [(ngModel)]” is a directive which will help us send data from the object to UI and vice versa.
  • Look at the way binding is applied to the object. It’s referring the property as “CurrentCustomer.CustomerName” and not just “CustomerName”. Why?? Because if you remember the object exposed from the “CustomerComponent” is “CurrentCustomer” object. So you need to qualify “CurrentCustomer.CustomerCode”.
HTML
<input type="text" [(ngModel)]="CurrentCustomer.CustomerName">

Image 17

  • Round brackets indicate data sent from UI to object.
  • Square brackets indicate data is sent from object to UI.
  • If both are present, then it’s a two way binding.

There would be times when we would like to display object data on the browser. By using “{{“ braces, we can display object data with HTML tags. In the below HTML, we are displaying “CustomerName” mixed with HTML BR tag. These braces are termed as “INTERPOLATION”. If you see the dictionary meaning of interpolation, it means inserting something of different nature into something else.

In the below code, we are inserting object data within HTML.

TypeScript
{{CurrentCustomer.CustomerName}}<br />

Below goes the full HTML UI code with binding directives and interpolation.

HTML
<div>
Name:
<input type="text" [(ngModel)]="CurrentCustomer.CustomerName"><br /><br />
Code:
<input type="text" [(ngModel)]="CurrentCustomer.CustomerCode"><br /><br />
Amount:
<input type="text" [(ngModel)]="CurrentCustomer.CustomerAmount"><br /><br />
</div>
{{CurrentCustomer.CustomerName}}<br /><br />
{{CurrentCustomer.CustomerCode}}<br /><br />
{{CurrentCustomer.CustomerAmount}}<br /><br />

Step 8: Creating the Module

Module is a container or you can say it’s a logical grouping of components and other services.

So the first import in this module is the “CustomerComponent” component.

TypeScript
import { CustomerComponent }   from '../Component/CustomerComponent';

We also need to import “BrowserModule” and “FormsModule” from core angular. “BrowserModule” has components by which we can write IF conditions and FOR loop. “FormsModule” provides directive functionality like “ngModel”, expressions and so on.

TypeScript
import { BrowserModule } from '@angular/platform-browser';
import {FormsModule} from "@angular/forms"

We also need to create a typescript class “MainModuleLibrary”. At this moment, this class does not have any code but it can have code which will provide component level logic like caching, initialization code for those group of components and so on.

TypeScript
export class MainModuleLibrary { }

To create a module, we need to use import “NgModule” from angular core. This helps us to define module directives.

TypeScript
import { NgModule }      from '@angular/core';

NgModule” has three properties:

  • Imports: If this module is utilizing other modules, we define the modules in this section.
  • Declarations: In this section, we define the components of the modules. For now, we only have one component ‘CustomerComponent”.
  • Bootstrap: This section defines the first component which will run. For example, we can have “HomeComponent”, “CustomerComponent” and so on. But the first component which will run is the “HomeComponent” so that we need to define in this section.
TypeScript
@NgModule({
    imports: [BrowserModule,
             FormsModule],
    declarations: [CustomerComponent],
    bootstrap: [CustomerComponent]
})

Below goes the full code of Angular module which we discussed in this section.

TypeScript
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {FormsModule} from "@angular/forms"
import { CustomerComponent }   from '../Component/CustomerComponent';

@NgModule({
    imports: [BrowserModule,
             FormsModule],
    declarations: [CustomerComponent],
    bootstrap: [CustomerComponent]
})
export class MainModuleLibrary { }

Step 9: Creating the “Startup.ts” File

Image 18

So we have created the UI, we have created the models, we have created components and these components are grouped into modules. In an Angular application, you can have many modules.

So you need to define the startup module. So let’s create a “Startup.ts” file which will define the startup module.

Below goes the “Startup.ts” file in which we have defined which module will be bootstrapped.

TypeScript
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { MainModuleLibrary } from '../Module/MainModuleLibrary';
const platform = platformBrowserDynamic();
platform.bootstrapModule(MainModuleLibrary);

Step 10: Invoking “Startup.ts” File using Main Angular Page

So let us create a startup HTML page which will invoke the “Startup.ts”. Now in this page, we will need to import four JavaScript framework files Shim, Zone, Meta-data and System JS as shown in the below code:

HTML
<script src="../../node_modules/core-js/client/shim.min.js"></script>
<script src="../../node_modules/zone.js/dist/zone.js"></script>
<script src="../../node_modules/reflect-metadata/Reflect.js"></script>
<script src="../../node_modules/systemjs/dist/system.src.js"></script>

Below are the use of JS files:

Shim.min.js This framework ensures that ES 6 JavaScript can run in old browsers.
Zone.js This framework ensures us to treat group of Async activities as one zone.
Reflect.js Helps us to apply meta-data on JavaScript classes. We are currently using @NgModule and @NgComponent as attributes.
System.js This module will helps to load JS files using module protocols like commonjs, AMD or UMD.

In this HTML page, we will are calling the “systemjs.config.js” file. This file will tell system JS which files to be loaded in the browser.

HTML
<script src="../systemjs.config.js"></script>
<script>
    System.config({
        "defaultJSExtensions": true
    });

    System.import('startup').catch(function (err) { console.error(err); });
</script>

In the “import”, we need to specify “startup” which will invoke “startup.js” file.

TypeScript
System.import('startup').catch(function (err) { console.error(err); });

Our customer screen in with the name “Customer.html”. So to load into this screen, we need to define a place holder. So in this place holder, our Customer HTML page will load.

HTML
<customer-ui></customer-ui>

If you remember when we created the component class, we had said to load the HTML page in a selector. So that selector is nothing but a tag (placeholder) to load our Customer page.

TypeScript
@Component({
    selector: "customer-ui",
    templateUrl: "../UI/Customer.html"
})

Below goes the full HTML page with all scripts and the place holder tag.

HTML
<!DOCTYPE html>
<html>
<head>
   
    <title></title>
	
	<meta charset="utf-8" />
</head>
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="../../node_modules/core-js/client/shim.min.js"></script>
<script src="../../node_modules/zone.js/dist/zone.js"></script>
<script src="../../node_modules/reflect-metadata/Reflect.js"></script>
<script src="../../node_modules/systemjs/dist/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="../systemjs.config.js"></script>
<script>
    System.config({
        "defaultJSExtensions": true
    });

    System.import('startup').catch(function (err) { console.error(err); });
</script>
<body>
   
    <customer-ui></customer-ui>

</body>

</html>

Step 11: Setting Up the Typescript Compiler

We also need to run typescript so that TS files gets compiled to JS files. So open the integrated terminal and type “tsc -w”. This will make typescript run continuously at the background. So as you type typescript will keep compiling when the file changes.

Image 19

Step 12: Running the http-server

So if everything is ok in Step 11, we now need to now run http server. To run server, we need to type “http-server” in the VS code integrated terminal as shown in the figure.

Image 20

In case your 80 port is blocked, you can run this server on a specific port using “http-server –p 99”.
This will run this server over 99 port.

Image 21

So once the web server is running, you can now browse to the main angular HTML page.
Main angular page means the page in which we have put the scripts, put the place holder, systemjs and so on.

Please note Customer.html is not the main page. This page will be loaded in the placeholder of main angular page.

Once the sites are running, type in one of the textboxes and see the automation of binding output in expression.

Run in two terminals. You can open two terminals by clicking on the “+” in terminal window. So in one window, you can run http-server and in other window, you can run typescript in watch mode.

Image 22

How to the Run the Source Code?

The source code that is attached in this book is without “node_modules” folder. So to run the code, you need to open the folder using VS code and then do a NPM using the integrated terminal on the folder where you have “package.json” file.

What's in the Next Article?

In the next article, i.e., Lab 3, we will look in to Angular SPA and Validation, click here to read the next article.

For further reading, do watch the below interview preparation videos and step by step video series:

History

  • 21st September, 2017: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)