Build Your First AngularJS 2 Application With TypeScript

Introduction

Angular is a platform for developing web and mobile applications. Angular 2 is not just an update of Angular 1.x but Angular 2.0 is re-written and has many breaking changes. It is completely written in TypeScript (to meet ES 6 specifications). There is a huge learning curve for the developers of Angular 2.

In this article, we will learn how to build and run Angular 2 application with TypeScript and how to establish the development environment.

Prerequisite

Node.js and npm must be installed in your machine as a prerequisite. To build and run Angular 2 application, node v4.x.x and npm v3.x.x will work fine.

Step 1: Create and configure the project.

In the first step, we create the project folder and add package definition and configuration file. Then, finally install all packages.

Angular application must have the following package definitions and configuration files.

package.json

It contains the list of packages for the app. The pakage.json file contains the project or application dependencies in "dependencies" property.

The dependencies section contains following three package categories.

  • Features - These packages provide our application with the framework and utility capabilities.
  • Polyfills - They plug gaps in the browser's JavaScript implementation. For example, core-js, rxjs, and zone.js etc.
  • Other - Other libraries that support the application, like bootstrap for HTML widgets, styling, etc.

In the example, I have used the following package.json file.

  1. {  
  2.    "name""TestAngular2",  
  3.    "version""1.0.0",  
  4.    "scripts": {  
  5.       "start""concurrently \"npm run tsc:w\" \"npm run lite\" ",  
  6.       "tsc""tsc",  
  7.       "tsc:w""tsc -w",  
  8.       "lite""lite-server",  
  9.       "typings""typings",  
  10.       "postinstall""typings install"  
  11.    },  
  12.    "license""ISC",  
  13.    "dependencies": {  
  14.       // Features of AngularJS  
  15.      "@angular/common""2.0.0-rc.5",  
  16.      "@angular/compiler""2.0.0-rc.5",  
  17.      "@angular/core""2.0.0-rc.5",  
  18.      "@angular/forms""0.3.0",  
  19.      "@angular/http""2.0.0-rc.5",  
  20.      "@angular/platform-browser""2.0.0-rc.5",  
  21.      "@angular/platform-browser-dynamic""2.0.0-rc.5",  
  22.      "@angular/router""3.0.0-rc.1",  
  23.      "@angular/router-deprecated""2.0.0-rc.2",  
  24.      "@angular/upgrade""2.0.0-rc.5",  
  25.         
  26.      // Polyfills   
  27.      "systemjs""0.19.27",  
  28.      "core-js""^2.4.0",  
  29.      "reflect-metadata""^0.1.3",  
  30.      "rxjs""5.0.0-beta.6",  
  31.      "zone.js""^0.6.12",  
  32.       
  33.      // Other required libraries  
  34.      "angular2-in-memory-web-api""0.0.15",  
  35.      "bootstrap""^3.3.6"  
  36.    },  
  37.    "devDependencies":{  
  38.       "concurrently""^2.0.0",  
  39.       "lite-server""^2.1.0",  
  40.       "typescript""^1.8.9",  
  41.       "typings":"^0.7.9"  
  42.    }  
  43. }  
Here, we have added several npm scripts in our package.json to handle the common development tasks. We have used the following scripts in package.json file.
  • npm start - runs the npm compiler and a server at the same time. Both are in "watch mode".
  • npm run tsc - runs the TypeScript compiler.
  • npm run tsc:w - runs the TypeScript compiler with watch mode.The process is continuously running and awaiting changes to TypeScript files and recompiling them.
  • npm run lite - runs the lite-server.
  • npm run typings - runs the typings tool.
  • npm run postinstall - npm calls it automatically after successful completion of package installation. This script installs the TypeScript definition files defined in typings.json

tsconfig.json

It is a TypeScript compiler configuration file. The primary language of Angular application development is a TypeScript. Since the browser is only capable of executing JavaScript, so the TypeScript needs to be transpiled into JavaScript with the tsc compiler and this requires some configurations. This file contains these configurations.

  1. {  
  2.    "compilerOptions": {  
  3.       //ECMAScript target version  
  4.       "target""ES5",  
  5.        // module code generation  
  6.       "module""system",  
  7.       //module resolution strategy  
  8.       "moduleResolution""node",  
  9.       // Generates corresponding '.map' file  
  10.       "sourceMap"true,  
  11.       // Emit design-type metadata for decorated  
  12.       // declarations  Metadata in source  
  13.       "emitDecoratorMetadata"true,  
  14.       // Enables experimental support for ES7 decorators  
  15.       "experimentalDecorators"true,  
  16.       // Do not emit comments to output  
  17.       "removeComments"false,  
  18.       "noImplicitAny"false,  
  19.       // Generates corresponding d.ts files  
  20.       "declaration"true  
  21.    },  
  22.    // Points folders and file to exclude  
  23.    "exclude": [  
  24.       "node_modules",  
  25.       "typings/main",  
  26.       "typings/main.d.ts"  
  27.    ]  
  28. }  
typings.json

Many JavaScript libraries, such as jQuery, AngularJS, and jasmine extend some features of the JavaScript environment but some syntax is not recognized by TypeScript compiler. Hence, it throws an error. TypeScript awares about the definition files that contain the information about the syntax which are not recognized by TypeScript compiler. The typings tool can find and fetch these files. We can install the typings tool with npm in package.json and add npm script to run automatically after the package installation completes.
  1. {  
  2.    "ambientDependencies": {  
  3.       "es6-shim""github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd",  
  4.       "jasmine""github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd"  
  5.    }  
  6. }  
systemjs.config.js

SystemJS is used to load the application and library modules. It is also known as Universal Dynamic Module Loader. It loads ES6 modules, CommonJS, global scripts,  and nodeJS. It is not able to load modules which have circular reference and binding support.
  1. (function(global) {  
  2.   // map tells the System loader where to look for things  
  3.   var map = {  
  4.     'app':                        'app'// 'dist',  
  5.     '@angular':                   'node_modules/@angular',  
  6.     'angular2-in-memory-web-api''node_modules/angular2-in-memory-web-api',  
  7.     'rxjs':                       'node_modules/rxjs'  
  8.   };  
  9.   // system loader get the information from packages about load when no filename and/or no extension  
  10.   var packages = {  
  11.     'app':                        { main: 'main.js',  defaultExtension: 'js' },  
  12.     'rxjs':                       { defaultExtension: 'js' },  
  13.     'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },  
  14.   };  
  15.     //Package include dependancies  
  16.   var ngPackageNames = [  
  17.     'common',  
  18.     'compiler',  
  19.     'core',  
  20.     'forms',  
  21.     'http',  
  22.     'platform-browser',  
  23.     'platform-browser-dynamic',  
  24.     'router',  
  25.     'router-deprecated',  
  26.     'upgrade',  
  27.   ];  
  28.   // Individual files (~300 requests):  
  29.   function packIndex(pkgName) {  
  30.     packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };  
  31.   }  
  32.   // Bundled (~40 requests):  
  33.   function packUmd(pkgName) {  
  34.     packages['@angular/'+pkgName] = { main: 'bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };  
  35.   }  
  36.   // Most environments should use UMD; some (Karma) need the individual index files  
  37.   var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;  
  38.   // Add package entries for angular packages  
  39.   ngPackageNames.forEach(setPackageConfig);  
  40.   var config = {  
  41.     map: map,  
  42.     packages: packages  
  43.   };  
  44.   System.config(config);  
  45. })(this);  
Install Packages

We have to install all the packages listed into the package.json file. We can install the package using the following command of npm.

npm install

Step 2: Create Angular Component.

Every Angular application has at least one root component which hosts the client UI experience. The component controls the portion of the View through associated template. In this example, I have created only one component named as "AppComponent".

Here, I have created a folder called "app" for my application and added component file (app.component.ts) within this newly created folder.

The component has required some essential structure. Angular component contains the following things:
  • One or more import statements to import required modules or library.
  • Component declaration using @Component keyword and it contains the template to be used by Angular application.
  • Define component class which controls the behavior of the View through its template.
  1. import { Component } from '@angular/core';  
  2. @Component({  
  3.   selector: 'test-app',  
  4.   template: '<h1>This is my First Angular 2 Application</h1>'  
  5. })  
  6. export class AppComponent { }  
Angular application is modular. That means, it is created by many files, each having a unique purpose. When we require something from  a library, then we need to import it. The @component decorator is contained by the module Angular 2 Core. So, we need to import this in our component file.

Component is a decorator function which takes an argument as metadata. It allows the associating meta with component class. Metadata is important for knowing how to create and use the component. The metadata has two fields - selector and template. The selector specifies a selector for HTML which represents the component. The template is nothing but HTML. It could contain the data binding to the component. The template might contain other components.

Component class may contain the model property and application logic. In the above example, our component class is empty. One more point here- We export the component class so that we can use it in other component by import.

Step 3: Create App.Module.ts

Every Angular application has at least one module. The root module can be called AppModule by convention. In this example, I have created app.module.ts in the app folder.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
  1. import { NgModule }      from '@angular/core';  
  2. import { BrowserModule } from '@angular/platform-browser';  
  3.   
  4. import { AppComponent }  from './app.component';  
  5.   
  6. @NgModule({  
  7.   imports:      [ BrowserModule ],  
  8.   declarations: [ AppComponent ],  
  9.   bootstrap:    [ AppComponent ]  
  10. })  
  11. export class AppModule { }  
The module contains three main sections:
  • imports - Imports the other module that is required in newly create module. The root module of the application should import the BrowserModule.
  • declarations - the components and directives that are used by this module.
  • bootstrap - It identifies the root component which bootstraps when the application starts.

Step 4: Add main.ts

The main.ts tells Angular to load the application module. In this example, I have created main.ts file within app folder.

  1. import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';  
  2. import { AppModule } from './app.module';  
  3. platformBrowserDynamic().bootstrapModule(AppModule);  
In the above example, main.ts file, I have imported two modules: platformBrowserDynamic and AppModule and then, I have called platformBrowserDynamic().bootstrapModule with AppModule.

Step 5: Create index.html file in the project root folder.

In the project root folder, I have created index.html file. This HTML file contains some JavaScript libraries, configuration files and component declarations in body tag. I have included core-js, zone.js, reflect.js, and systemJS library for module.
  1. <html>  
  2.   <head>  
  3.     <title>Angular 2 Test Example</title>  
  4.     <meta charset="UTF-8">  
  5.     <meta name="viewport" content="width=device-width, initial-scale=1">  
  6.       
  7.     <!-- Load libraries -->  
  8.      <!-- Polyfill(s) for older browsers -->  
  9.     <script src="node_modules/core-js/client/shim.min.js"></script>  
  10.     <script src="node_modules/zone.js/dist/zone.js"></script>  
  11.     <script src="node_modules/reflect-metadata/Reflect.js"></script>  
  12.     <script src="node_modules/systemjs/dist/system.src.js"></script>  
  13.     <!-- Configure SystemJS -->  
  14.     <script src="systemjs.config.js"></script>  
  15.     <script>  
  16.       System.import('app').catch(function(err){ console.error(err); });  
  17.     </script>  
  18.   </head>  
  19.   <!-- Display the application -->  
  20.   <body>  
  21.     <test-app>Loading...</test-app>  
  22.   </body>  
  23. </html>  
When bootstrapModule function of main.ts is called, it reads the "AppModule" metadata and looks for the "Appcomponent" in bootstrap component. It finds the "test-app" selector and renders our application View between this selector.

Step 6: Build and run the application.

We can run this Angular application using the following command from terminal window.

npm start

command

When we run this command, there are two processes running parallelly on node server: Compile the Typescript in watch mode and lite server load index.html in browser.

The lite server and Typescript compiler continuously watch the application and if they find any changes, they recompile the Typescript into JavaScript and refresh the browser to display the HTML with new changes.

Let's enhance some code in app.component.ts file, as following.

Angular has syntax feature called "template reference variables". It allows us the  direct access to any element of template. We can declare the template reference variables by hash or pound character (#). This does not work until we bind some event.

app.component.ts
  1. import  
  2. {  
  3.     Component  
  4. } from '@angular/core';  
  5. @Component  
  6. ({  
  7.     selector: 'test-app',  
  8.     template: '<h1>This is my First Angular 2 Application</h1>' + '<br/>' + '<input #txtName type = "text" (keyup)="0" />' + '<br/> ' + '<p>You have Enter: {{txtName.value}}</p>'  
  9. })  
  10. export class AppComponent {}  
Output

Output

Now, we run this demo. Type in to the text box and watch. It will update the textbox value for each key stroke. 

Next Recommended Readings