Saturday 17 June 2017

Angular 2 Tutorial - The Architecture of an Angular 2 Application


Angular 2 is beta now, what this means is though it is not production ready, the angular team is confident that you can build apps with Angular 2. This also means that when Angular 2 is ready for production there won’t be major changes in the implementation compared to what it is now.
Though one might argue it is still too early, we are suggesting to you that this is the right time to get acquainted with it and get your hands dirty. This will give you a head-start when Angular 2 is ready and when you are ready to develop production apps with Angular 2.
Whenever we get started with a new framework it is of pivotal importance to know how the framework works. So we first need to understand the architecture of Angular 2 and get familiar with some of the key concepts of Angular 2 followed by which we will set up our development environment.

Architectural Overview

Angular is designed to be modular, an Angular 2 app comprises of several components, which are connected via routing or selectors, these components may have templates attached to it which may display component properties and attach events to interact with the properties. A component may use a service, to access a particular feature or perform a very specific task. Services must be injected into components before they can be used from within the component, this is referred to as Dependency Injection, which has also been a key feature of Angular 1.x.
enter image description here
The above diagram shows an overall overview of the basic architecture of a skeleton Angular 2 app. Lets
look into few of the important concepts in detail.

Modules

Angular App comprises of several Modules, a module typically exports something of a purpose. A module is a set of similar utilities that perform a similar task. Typically a module may export a class which we may be imported in other modules. Angular 2 itself ships in large modules, some of them are ‘angular/core‘, ‘angular/router‘ and there are more.

Components

Components are the basic building blocks of an Angular 2 app. A component is typically a type-script class which has a template attached, it usually assembles a screen, ui-element or a route in the application. A component may have child components. Components can be navigated using routing or selectors.
A component has a metadata/ decorator associated which describes the component. Metadata tells angular that the associated TypeScript class is actually to be considered as a component.

Services

A good Angular 2 application is one in which specific tasks are assigned to different services. A component may consume these services to perform these tasks. Typically a component should only deal with the user experience and the display of properties and use services to perform heavy behind the scenes operations. A service must be injected in to the controller before it can be used. This is done via dependency injection.

Dependency Injection

One of the key features of AngularJS is the dependency injection. Components need to use services to perform tasks, and these services are injected into the component via the injector. The injector provides the instance of the service, so that it can be used in the component. The idea behind dependency injection is to separate out concerns into smaller units and make components depend on these units to perform specific tasks, making your application more manageable and easy to unit test.

Directives

Directives are everywhere in Angular 2. A directive is a TypeScript Class with a metadata. Directives may or may not have a template attached. Component is an example of a directive with a template. There are two kinds of directives in Angular 2, structural and attribute directives. Structural directives modify the structure or layout of the DOM. Attribute directives alter the behavior of the elements. Some of the examples of pre-built directives are ngForngIfngSwitchngModel etc.

TypeScript

Angular 2 application can be written in JavaScriptDart or TypeScript. For this tutorial we will be looking at a setup with TypeScript.
TypeScript is Microsoft’s extension of JavaScript. TypeScript is a super-set of ES6 which in turn is a super set of the standard JavaScript (ES5). This means whatever that can be done with ES5 or ES6 can be written in TypeScript. In-fact you can most of the times write in plain old JavaScript in a TypeScript program. TypeScripts adds important features like annotationsinterfaces and types in addition to classes and modules offered by ES6 on top of ES5. Browsers do not understand TypeScript
and hence it has to be transpired into ES5 and this can be done using the TypeScript compiler.

Development Setup

This section will deal with the setup required to write Angular 2 apps in TypeScript. In the process to do so, we will be building a simplest form of Angular 2 app and also have a look at a skeleton folder structure for Angular 2 apps.
In short this section will setup our base to eventually build better and larger apps with Angular 2.
Note: This article is written for Angular 2.0 beta. The Angular 2 repo is subjected to change, if you find any discrepancies please write to us about it and if possible suggest the fixes

Install Node

npm will be used as our package manager and our app will run on node. If you have node installed awesome; if not, then head over to the official node website and download the appropriate version.

Setup a Skeleton App

Now lets get a skeleton app structure from an app that I have already created. I will explain the contents later, for now follow along.
Clone the repository.
Alternatively you can download and extract the code form here.

App structure

Once you have completed the above step successfully, you should be able to see the following project structure.
enter image description here
APP
Angular apps are built out of several linked or nested components, our app folder here contains a components directory, which will hold the apps different components.
ASSETS
Assets is a directory which will contain non angular data required by our app, for example style-sheets.
PACKAGE.JSON
Package.json holds information that allows npm to identify the project dependencies and help install them with a single command.
Below is our package.json file, which is similar to the one provide by the Angular 2 team for the quick-start application. It contains a starter-set of dependencies required by Angular 2 project identified by the Angular 2 team.
package.json
{
  "name": "angular2-setup",
  "version": "1.0.0",
  "scripts": {
    "start": "concurrent \"npm run tsc:w\" \"npm run lite\" ",<br />
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "lite": "lite-server",
    "typings": "typings",
    "postinstall": "typings install"
  },
  "license": "ISC",
  "dependencies": {
    "angular2": "2.0.0-beta.7",
    "systemjs": "0.19.22",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.2",
    "zone.js": "0.5.15"
  },
  "devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.1.0",
    "typescript": "^1.7.5",
    "typings":"^0.6.8"
  }
}
While running the application I encountered a type-error in the chrome browser, to fix this I upgraded the es6-shim version from 0.33.3 (which is recommended by Angular 2 team) to 0.34.4. Details can be found here.
The scripts defined in the file run few commands for example npm start will run the typescript compiler (tsc) and then run lite-server. Commands defined in post install run after npm has finished installing other dependencies.

tsconfig.json

tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}
tsconfig.json is the configuration file for TypeScript projects. It holds configurations such as compiler options, files to be included excluded, etc. The compilerOptions instructs TypeScript compiler, how to compile typescript files.
The exclude block instructs typescript compiler to exclude folders and files.
TYPINGS.JSON
typings.json
{
  "ambientDependencies": {
    "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#6697d6f7dadbf5773cb40ecda35a76027e0783b2"
  }
}
Some libraries/ framework extend JavaScript environment with features that type script compiler does not support. To make the typescript compiler understand these enhancements we add respective d.ts files in typings.json

First Component

/app/components/welcome/welcome.component.ts
import {Component} from 'angular2/core';
@Component({
    selector: 'my-app',
    templateUrl: '../app/components/welcome/welcome.template.html'
})
export class WelcomeComponent {
    constructor() {
        var self = this;
        self.displayName = '';
    }
    setDisplayName(value){
        var self = this;
        self.displayName = value;
    }
}
This is the complete welcome.ts file. Parts of code are explained below.
import {Component} (welcome.component.ts)
import {Component} from 'angular2/core';
To create a component we will need the component class which is shipped with ‘angular2/core’ module. importstatement tells TypeScript to import some exported entity from a module.
Decorator (welcome.component.ts)
@Component({
    selector: 'my-app',
    templateUrl: '../app/components/welcome/welcome.template.html'
})
The @component decorator/metadata describes a component and also tells Angular the the following class has to be treated as an Angular Component. The selector property describes the element name for our Component. So where ever we will use the element <my-app></my-app>, Angular will render our component.
Class (welcome.component.ts)
export class WelcomeComponent {
    constructor() {
        var self = this;
        self.displayName = '';
    }
    setDisplayName(value){
        var self = this;
        self.displayName = value;
    }
}
A class contains logic that would display, modify properties to be displayed to the user in the UI. We are exporting the class, so that we can import it some where else.
Our WelcomeComponent contains a constructor() function and a setDisplayName() method. A constructor is defined with the constructor key word in TypeScript or in ES6.
In Angular 1 we would do using a controller what a component class does in Angular 2.
/app/components/welcome/welcome.template.html
<h1 class="displayHead" *ngIf="!!displayName">Welcome to the world of Angular 2</h1>

<h2 class="userName" [hidden]="!displayName">{{displayName}}</h2>

<div *ngIf="!displayName">
    <label>Enter Your Name</label>
    <input [(ngModel)]="name"/>
    <button (click)="setDisplayName(name)">Enter</button>
</div
We won’t be going into details on events and property bindings in this tutorial, but here is some explanation to above template.
  • [hidden]: Property binding
  • (click): Event Binding. We are invoking setDisplayName method on click event.
  • [(ngModel)]: This is how you do, two-way data-binding in Angular 2

index.html

index.html
<html>
  <head>
    <title>Angular 2 QuickSetup</title>
    <meta name="viewport" content="width=device-width, initial-scale=1"><br />
    <link rel="stylesheet" type="text/css" href="assets/styles/style.css">
    <!-- 1. Load libraries -->
    <!-- IE required polyfills, in this exact order -->
    <script src="node_modules/es6-shim/es6-shim.min.js"></script>
    <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
    <!-- 2. Configure SystemJS -->
    <script>
      System.config({
        packages: {
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('app/main')
            .then(null, console.error.bind(console));
    </script>
  </head>
  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>
</html>
In index.html we are loading our required libraries and configuring systemJS.
Systemjs is our module loader. By defining packages in System.config we are setting systemjs setting for files loaded from ‘app/’ folder. We are setting the defaultExtension to js since we will be loading files transpiled into .jsfrom .tsSystems.import('app/main') loads the main.ts file where we are bootstraping the application, we will have a look at main.ts below. Systemjs configurations may deffer depending on the project folder structure. You can lean more about Systemjs configurations here.
Finally we are loading our welcome component by placing the my-app selector. If you remember we named our component element as my-app

Bootstrapping app with main.ts

main.ts
import {bootstrap} from 'angular2/platform/browser'
import {WelcomeComponent} from './components/welcome/welcome.component'
bootstrap(WelcomeComponent);
Here we tell angular to load our WelcomeComponent i.e the root component.

Run the app

Before running the app we need to do one more thing that is left out. Install all the required npm packages. Fire up your terminal and navigate to the working directory and run the following command.
 npm install
This may take a while, during the installation you may see some warnings but that is fine.
Next, to run our first Angular 2 app execute the below command.
npm start
This would fire up the lite server and run our app in the browser.
enter image description here
So here we have our first app with Angular 2. Download and play around with the code and explore new stuffs, you will learn more when you will try it yourself.

Conclusion

This tutorial intended to acquaint you with Angular 2 and set us up on mark to build larger apps with it. We have barely scratched the surface and there is more to learn. Stay tuned we will go into further details and build real apps with Angular 2 in coming tutorials.

1 comment:

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...