Angular Learning (Part1)
By: Tariqul Islam
Tags: Angular, Rxjs, Typescript, Learning And Development, Material Design

Angular is a full phased Frontend Development framework. We can acually don’t need to configure anything for start developing with this framework. It has its own routing, http, testing module, which has already well configured with it. so no need to extra configuration. The Most valuable feature is it has its own compect CLI. I told compect CLI, because we can generate controller, class, enums and service by only provide the single line of command, it will automaically configure the things in codebase. It’s has integrated with cool feature like RxJS, so we can do Reactive programming easily with Angular.

Prerequsites of Angular

Node JS NPM/ Yarn Angular Cli Angular Material UI.

Install angular Cli

> npm install -g @angular/cli

Then create the folder in your pc name angular-playground

> ng new my-app

Please select those option during generating the application

Angular Router -> select yes

Application wide style SCSS -> select yes

To run the project

> ng serve -o

Main Structure of the project

|--my-app

|---- e2e (end to end test folder)

|---- src (Source code folder)

|-------- app (Contains modules, services, Component and classes)

|-------- environments (environment configuration file)

|-------- asstes (Static image and logo and assest files and folder)

|-------- index.html (Entry point html file for application)

|-------- main.ts (Entry point typescript file and boostraping app)

|-------- polyfills.ts

|-------- styles.scss (Main and Global Style file)

|-------- test.ts (Test Configuration file)

|---- tsconfig.app.json (type script configuration file)

|---- tslint.json (Typpscript lint file)

|---- karma.config.js (Karma test configuration file)

|---- package.json (Npm Package defination and Node Scripting file)

|---- .browserrslistrc (Supported Browser list config file)

|---- angular.json (Angular configuration file)

|---- .editorconfig (IDE formatting configuration file)

Before we start we can discuss about some feature which related to Angular

Component

Component is the fundamental block for angular application. component can be reuseable and composable. When we generate the project angular add the root component named AppComponent , it use for boostrap the angular application.

I have plan to create the components folder and add the home component to it for, so we can easy arrange the components to application, so other new developer can undrestand where is the components in application.

> ng g c components/home

after running the command 4 files for home component are generated to /src/components/home folder

src/app/components/home/home.component.scss

src/app/components/home/home.component.html

src/app/components/home/home.component.spec.ts

src/app/components/home/home.component.ts

home.component.ts , where we can add the typescript codes, methods, doing the reactive programming and handle the methods, component behaveior.

home.component.scss we can add the style for specific component. When i generate the project select scss as style for application. that why it generate that file of adding the style to it.

home.component.html using for adding the html template and databinding, allow you represent webview to broser ,which are processing in Component Class.

home.component.spec.ts , we can add the unit test to this class for testing the component validity and behaveior.

Interpolation

String interpolation is the most pouplar way to render and embedding expression and binding the data in template or mark up text. Angular by default, uses double curly braces, {{ and }} for interpolation.

<h3>First Name: {{ firstName }}</h3>

Template expressions

Template expression is the another procedures to binding the value and expression to template and Markeup text and attributes. Its use for property binding Form element and HTML element and component and directives.

We can add the template expression with follwoing syntax [property]="expression" .

Decorator

Decorator is a function which provide functionality to add extra meta data for Angular class, there is many types of decorator are introducted in Angular. such as

Class Decorator which express the intent of the class, it allows us to define the intent without having acually put the code inside the class. It allows us to attached the code and behavior with modifing the class at angular class instance.

Such as @Component decorators, where we can define the html selector where for render template , template where developer can specify HTML template for represent the data of angular class, styleUrls using for define the external style file, which will applied for specific component.

input {Component, Input} from '@angular/core' @Component ({

selector: 'home'

template: "<div></div>",

styleUrls: "./home.scss"

})

export class ExampleComponent {

@Input()

exampleProperty: string;

}

Property Decorator we can define the property in class. such as @input decorator which tell the angular compiler we got the property about input, it creates the input binding to template with property name and link to specific input in template. Such as

@Input()

Where we can control the template form input, how it’s behave with angular class.

@Method Decorator, We will dicuss about at my next part of the series.

Directives

Attribute directive

Attribute directive changes the appearance or behaviors of the DOM element.

We have generate the directive By

> ng generate directive highlight

It Generate the below Directive for where we can control the Angular component rendering behaveior.

ElementRef,

@

selector: '[appHighlight]'

})

export class HighlightDirective {

@ import { Directive HostListener } from ‘@angular/core’; Directive ({selector: '[appHighlight]'})export class HighlightDirective { HostListener ('mouseenter') onMouseEnter() { this.highlight('yellow');

}



this.highlight(null);

}



private highlight(color: string) { HostListener ('mouseleave') onMouseLeave() {this.highlight(null);private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color;

}

}

Then you can control the dom element for this class

<p appHighlight>Higlight Me!</p>

Structural Directive

Structural directive are repsonsible for HTML layout, it sapes and reshapes the DOM structure typically adding, removing and manipulate the elements

<div *ngIf="name">{{name}}</div>

* is the syntactic suger for somting bit more complicated

<ng-template [ngIf]="name">

<div>{{name}}</div>

</ng-template>

Builtin Attribute directives listen to and modify the behavior of other HTML elements, attributes, properties, and components. You usually apply them to elements as if they were HTML attributes, hence the name. Those are

1. NgClass

2. NgStyle

3. NgModel

Pipe

There is lots of Pipe are available to Angular JS, Pipe will helps you to add the more cleaner code in Angular Template. If want to format the datetime, and want to Display the Json Object in Template you should use the pipe for that. Asnyc pipe is special pipe, by using it we can not add the subribe method to Obserable , it will automatically subscribe. Angular also provide the functionality to add custom pipe for Angular Template.

Built in Pipe Async Pipe Custom Pipe

We can declar the pipe in template by follwing structure

<div>{ expression or fieldname | pipname }</div>

If we use the datetime

<div>{{ obj.dateitme | datetime }}</div>

<div>{{ obj.person | json }}</div>

<div> {{ obj.price | currency:'JPY' }}

In this part of the application we just only discuss about the Reactive Form apporach to consume the data from form

HTTP module with Obserable to consume the data from ApiEndpoint Using Service

First Import the HttpClientModule to below to src/app/app.module.ts

import {HttpClientModule} from "@angular/common/http";

Then import it to app component src/app/app.module.ts file import section

imports: [

BrowserModule,

AppRoutingModule,

HttpClientModule

],

We are using Model to consume the data from external api to show into angular application.

To make clean structure i create the models folder and add the post.model.ts file into it.

in src/app/models/post.model.ts file add the following code bellow code to model class

export class PostModel { constructor(

public body: string,

public id: number,

public title: string,

public userid: number) {} }

PostModel is a class, i follow the ES6 contructor to implement the attribute of the Model class

Then we need to generate service, where we consume api data by obserable and http module of angular

> ng g service services/Post

After generating the code by Angular code strucutre is like below in Service file.

@Injectable({

providedIn: 'root'

})

export class PostService {

constructor() { }

}

Now we have some question in mind,

What is Injectable() decorator?

What exactly does providedIn do?

For service, Normally we have to add it to any Module as provider section for accessing the Service we created for application.

Providede in takes those value

providedIn: Type<any> | 'root' | null

When we add the value root to injector we can access the Service application wide no need to add it to module and other service as providers.

When you provide the service at the root level, Angular creates a single, shared instance of service and injects it into any class that asks for it.

providedIn: Module

By specify that a service should be provided in a particular @NgModule. For example, if you don’t want a service to be available to applications unless they import a module you’ve created, you can specify that the service should be provided in the module

import { Injectable } from '@angular/core';

import { UserModule } from './user.module'; @Injectable({

providedIn: HomeModule,

})

export class PostService {

}

Developer can also declare a provider for the service within the module:

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

import { UserService } from './user.service'; @NgModule({

providers: [UserService],

})

export class UserModule {

}

To consume the data for example purpose i use jsonplace holder as endpoint

The following code i applying the http module and RxJS Reactive Module to consume the data to PostService

import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http'

import {Observable} from 'rxjs'

import { PostModel } from '../models/post/post.model'; @Injectable({

providedIn: 'root'

})

export class PostService {

private url: string = 'https://jsonplaceholder.typicode.com/posts'; constructor(private httpClient: HttpClient) { } public getPosts(): Observable<PostModel[]> {

return this.httpClient.get<PostModel[]>(this.url)

}

}

Declare the api endpoint to url variable as string

private url: string = 'https://jsonplaceholder.typicode.com/posts';

To consume the data from api i declare the getPosts() function and it returns the Obserable of PostModel which using HttpClient library to consume the data from api. To avoid the compile time error declare the type for return value as Obserable<PostModel[]>

You have some question in mind, what is obserable?

Obserable: A representation of any set of values over any amount of time. This is the most basic building block of RxJS.

Observable instance has a subscriber function. This is the function that is executed when a consumer calls the subscribe() method. The subscriber function defines how to obtain or generate values or messages to be published.

We have to Subscribe the Obserable to load the postlist to home component in file src/app/components/home/home.component.ts.

In onInit() function i will subscribe the postlist obserable data , later use it to template file

import { Component, OnInit } from '@angular/core';

import { PostModel } from 'src/app/models/post/post.model';

import { PostService } from 'src/app/services/post.service'; @Component({

selector: 'app-home',

templateUrl: './home.component.html',

styleUrls: ['./home.component.scss']

}) export class HomeComponent implements OnInit { name: string = "Angular Application Example"

posts = new Array<PostModel>()



constructor(private service:PostService) { } ngOnInit(): void {

this.service.getPosts().subscribe(res => {

this.posts = res.map(item => {

return new PostModel(

item.body,

item.id,

item.title,

item.userid

)

})

})

}

}

In the constructor , we inject the PostService using Dependency Injection pattern. So we can access the PostService implemented methods and function in HomeComponent class.

getPost funciton return the Obserable of PostModel array of data, so we can not use it to template to render it to pages in web browser. So we need to serilized by PostModel using javascript map function which data is return by subscribe function.

Then add the following below code snappit to home.component.html file to render the post list of articles.

<div class="container">

<table>

<tr>

<th>ID</th>

<th>Body</th>

<th>Title</th>

<th>UserID</th>

</tr>

<tr *ngFor="let post of posts">

<td>{{ post.id }}</td>

<td>{{ post.body }}</td>

<td>{{ post.title }}</td>

<td>{{ post.userId }}</td>

</tr>

</table>

</div>

we using the *ngFor directive to iterate through the list of post element. *ngFor directive are works like below structure

*ngFor="let <item> of <item-list>"

The output of the all the code doing for this section are shown below in browser in http://localhost:4200

Angular Material UI Integration

Go to Terminal and run that command below

> ng add @angular/material

Then select Deep Purple or Indigo/Pink as theme of angular material ui, You can also select the other one if you want. My Preference is to use Indigo/Pink .

If you’re using Angular CLI, this is as simple as including one line in your app.component.scss file:

@import '@angular/material/prebuilt-themes/indigo-pink.css';

Then import the individul Angular Materual UI Component Module to app.component.js in file

import {MatToolbarModule} from "@angular/material/toolbar"

import {MatIconModule} from "@angular/material/icon"

import {MatTableModule} from "@angular/material/table"

After import you have to add it to import section for app module , otherwise you do not get access to component.

imports: [

BrowserModule,

AppRoutingModule,

HttpClientModule,

BrowserAnimationsModule,

MatToolbarModule,

MatIconModule,

MatTableModule

],

If you get any error in command line during build the angular app like below example during add the Angular Material UI Component to module file.





This likely means that the library (



14 export declare class MatMenuModule {

~~~~~~~~~~~~~ ERROR in node_modules/@angular/material/menu/menu-module.d.ts:14:22 - error NG6002: Appears in the NgModule.imports of AppModule, but could not be resolved to an NgModule class.This likely means that the library ( @angular/material /menu) which declares MatMenuModule has not been processed correctly by ngcc, or is not compatible with Angular Ivy. Check if a newer version of the library is available, and update if so. Also consider checking with the library's authors to see if the library is expected to be compatible with Ivy.14 export declare class MatMenuModule {~~~~~~~~~~~~~

Stop the angular app and run the following command below

> npm install && ng serve

For windows

> npm install | ng serve

To check Angular Material UI is added successfully to our project, adding the navbar for Angular Material UI to app.component.html file.

Remove Angular generated code at app.component.html, then add this code to check

<div>

<mat-toolbar color="primary">

<mat-toolbar-row>

<span>My App</span>

<span class="example-spacer"></span>

<button mat-icon-button class="example-icon" aria-label="Example icon-button with menu icon">

<mat-icon>menu</mat-icon>

</button>

</mat-toolbar-row>

</mat-toolbar>

<app-home></app-home>

</div>

<router-outlet></router-outlet>

<app-home></app-home> is a home component, when we want to add component to other component,

we have to add by the selector name with dom structure of the component like that syntax.

To align the Toolbar element we use the flex in app.component.scss file

@import '@angular/material/prebuilt-themes/indigo-pink.css';

.example-spacer {

flex: 1 1 auto;

}

Change the Normal Table to Angular UI Matetial Table by following procedure Home.component.html

<div class="container">

<table mat-table [dataSource]="posts" class="mat-elevation-z8">

<!-- Id Column -->

<ng-container matColumnDef="id">

<th mat-header-cell *matHeaderCellDef> No. </th>

<td mat-cell *matCellDef="let element"> {{element.id}}</td> </ng-container>

<!-- Name Column -->

<ng-container matColumnDef="body">

<th mat-header-cell *matHeaderCellDef> Name </th>

<td mat-cell *matCellDef="let element"> {{element.body}}</td>.

</ng-container>

<!-- Title Column --> <ng-container matColumnDef="title">

<th mat-header-cell *matHeaderCellDef> Weight </th>

<td mat-cell *matCellDef="let element"> {{element.title}} </td> </ng-container> <!-- Symbol Column -->

<ng-container matColumnDef="userId">

<th mat-header-cell *matHeaderCellDef> User Id</th>

<td mat-cell *matCellDef="let element"> {{element.userId}} </td>

</ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>

<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table>

</div>

Routing with Angular JS

> ng g c components/about-us

All the following code to app-routing.module.ts file.

import {AboutUsComponent} from "./components/about-us/about-us.component"

import {HomeComponent} from "./components/home/home.component" const routes: Routes = [

{path: '', component: HomeComponent},

{path: 'home', component: HomeComponent},

{path: 'about-us', component: AboutUsComponent}

];

path: '' routing is serve when, there is no routing value to it, it will shows the HomeComponent information.

Remove the <app-home></app-home> from app.component.html file, because we don’t need it, Angular Router will handle all the component you specify in routing file.

<div>

<mat-toolbar color="primary">

<mat-toolbar-row>

<span>My App</span>

<a href="/home" mat-raised-button color="primary">Home</a>

<a href="/about-us" mat-raised-button color="primary">About</a>. <span class="example-spacer"></span> <button mat-icon-button class="example-icon" aria-label="Example icon-button with menu icon">

<mat-icon>menu</mat-icon>

</button>

</mat-toolbar-row>

</mat-toolbar>

</div>

<router-outlet></router-outlet>

Reactive Form Modules

Add the ReactiveFormsModule to app.component.js file to add into module

Import the module

import { ReactiveFormsModule } from '@angular/forms';

Add it to imports to enable the ReactiveFormsModule

imports: [

.......

ReactiveFormsModule ],

For example purpose, I will work on AboutUs component to contact form, add the formControl to about-us.component.js in class

import { Component, OnInit } from '@angular/core';

import { FormControl, FormGroup } from '@angular/forms'; @Component({

selector: 'app-about-us',

templateUrl: './about-us.component.html',

styleUrls: ['./about-us.component.scss']

})

export class AboutUsComponent implements OnInit { contactForm = new FormGroup({

name: new FormControl(''),

email: new FormControl(''),

details: new FormControl(''),

}) constructor() { }



ngOnInit(): void {} }

We add the FormControl to FormGorup, so we can grouping the FormControl of the template. ReactiveFormModule already include those control to handle the form element of template. we delare the contactForm later will specify it to template.

In about-us.component.scss file add the following code for simple design

.example-form {

min-width: 150px;

max-width: 500px;

width: 100%;

}



.example-full-width {

width: 100%;

}

In AboutUs component, we can add the following code below

<form [formGroup]="contactForm" class="example-form">

<mat-form-field class="example-full-width">

<mat-label>Name</mat-label>

<input matInput placeholder="tom" formControlName="name">.

</mat-form-field>

<mat-form-field class="example-full-width">



<mat-label>Email</mat-label>

<input matInput placeholder="example@gmail.com" formControlName="email" >

</mat-form-field>



<mat-form-field class="example-full-width">

<mat-label>Details</mat-label>

<textarea matInput placeholder="Please Contact" formControlName="details"></textarea>

</mat-form-field> <button mat-raised-button color="primary">Primary</button>

</form>

In this code sanppit, i already implement the Material UI Form Component. In the first line i specify the [formGroup]="contactFrom" which will automaically bind the contactForm (formGroup)variable which is declare in about-us.component.ts file. formControlName will create the binding between formControl which are spcify in formGroup .

Add the onSubmit function to about-us.component.ts file to listen to form element when sumitting.

export class AboutUsComponent implements OnInit {

....... onSubmit() {

console.warn(this.contactForm.value)

} }

Add the submit function to angular template ngSubmit like below, when we submit the form this function will tiggered in Angular class file named AboutComponent.

<form [formGroup]="contactForm" (ngSubmit)="onSubmit()" class="example-form">

Then add the some code to button to disabled the button when form value is valid after submiting

<button type="submit" mat-raised-button [disabled]="!profileForm.valid" color="primary">Save</button>

Output of the code is

You can find all source code in