Pranay Rana: Typescript
Showing posts with label Typescript. Show all posts
Showing posts with label Typescript. Show all posts

Saturday, June 30, 2018

Different Kind of for loop construct in JavaScript/TypeScript

For Loop is very basic type of loop exist in all programming language. For loops allows to go over each items in iterable objects and allows to access each item of iterable objects. Each programming language provide different type of for loop to achieve purpose of iterating over iterable object and access each element to perform operation.

All programming language provide for loop (for(int i=0; i< array.length; i++)) i.e. indexed based and ForEach ( foreach(var ele in array)) i.e. element base.

But JavaScript/ TypeScript provides different type of for loops apart from basic once. Below are 4 different kind of JavaScript/ TypeScript

1. for
One of the most used and basic for loop to allows iterate block of code for predefined number.

Syntax
for (statement 1; statement 2; statement 3) {
    code block to be executed
}

Example code :
const array = [1,10,6,45,32];
for(let i=0;i< array.length;i++) {
 console.log(array[i]);
}

Above code shows one example how to use it, code prints each array item by rotating from 0 up to array length. Above example made using array of numbers but in real application one can create for loop just by setting numbers and execute block of code repeatedly for predefined numbers. So this loop is not restricted for iterables only.

2. for..of
allows to go over each item in iterable (Ex. like array, string, Map, Set, etc.)

Syntax
for (variable of iterable) {
  statement
}

Example code :
const array = [1,10,6,45,32];
for (const element of array) {
 console.log(element);
}

Above code does same thing as for loop code discussed above, go though each element of array and print.
But difference is for...of loop works only on the iterable objects and for each element of iterable, where as in basic for loop one externally need to set predefined number like from and to to execute block of code. So it helpful when want to execute on each element or by using each element of iterable.

Angular framework also have structural directive calle *ngFor for displaying data. Read more : Dynamic Html Structure with - *ngIf, *ngFor & ngSwitch

3. For In
allows to iterate over each property of object. This loop is different then other loops as it allows to go though object properties.

Syntax
for (variable in object) {
}

Example code:
const obj = { a : 1, b: 'Xyz', c:'123'};
for(let prop in obj) {
 console.log(prop +' : '+  obj[prop]);
}

code above prints each object property and value of it. Below is use cases when for..in very helpful.
  • Loop is useful when object structure is unknown (When object received as response from external api http call) and there is need of go through each property of object and display it.
  • It also useful when there is indexed (interface, class) object in type script and there is need of go through each indexed item without knowing key.
    Example:
    interface Product {
        [key: number]: string;
    }
    
    let products : Product = { };
    products[10]='xyz';
    products[20]='abc';
    
    for(let key in products) {
     console.log(key + ' : ' + products[key]);
    } 

4.  forEach(ele=> {} );
allows to iterate over each item in array and  execute function for each element in iterable.

Syntax
arr.forEach(function callback(currentValue[, index[, array]]) {
    //your iterator
}[, thisArg]);

Example code:
const array = [1,10,6,45,32];
array.forEach((element,index)=> {
 console.log(index +' ' +element);
});

Above code execute function for each element of array and prints element value & index of element in array.
Different from basic for is,  execute function for each element without knowing size of iterable & improves redability and difference from and for..of  is also allows to get index of each element which is not possible in for..of.

Wrapping up
Javascript/typescript provides 4 different which can be useful in different way based on simplicity & redablity of code , performance of loop and sometimes based on situation like for..in used for go through each property of object or each index of indexed class/interface.. 

Tuesday, June 12, 2018

Way to handle Parallel Multiple Requests

In web application Multiple requests means when there is need of making more then one Http requests to get result response and display to end user on web page. Multiple requests can be
  • Dependent Request
    Http Request is dependent request when it waits for result which needs to be given by other Http request i.e. parent request. Read more about how to perform Dependent request in angular here : Angular Dependent Request
  • Parallel Request
  • When client code fire more then one Http request on server and that all fired request get executed on server simultaneously.
Parallel Http requests are required when application need to make simultaneously to get data and display result to end user. For Example - In online shopping application, on order history page when use clicks on old Order to get detail , details page should display order details with all products detail which is associated with order.
Mostly in application database when order get saved its will save order details with associated product ids not full product. so to achieve this requirement once order data available with product ids, client code need to get fire multiple requests basically for each product id to get detail of product associated with order.

Below picture shows how parallel request get executed by approach going to discuss below.




Below are the way client code make parallel Http request and handle response of the requests to display final result with help of RxJs functions.

1. MergeMap

RxJs function mergeMap allows to fire out multiple request and handle response of each request to produce result. Function flatten inner observable(s) and allow to control each observable. Read more : MergeMap

    import { mergeMap, catchError } from 'rxjs/operators'; 
    megeMapTest() {
    const prouctIds: number[] = [1, 2, 3];
    const requests = from(prouctIds)
      .pipe(
      mergeMap(id => this.productService.getProduct(id))
      );

    requests.subscribe(
      data => console.log(data), //process item or push it to array 
      err => console.log(err));
 } 

In above code, important thing to note out is mergeMap, it merges all parallel requests fired to get product in one observable stream (array of observable) and then allows that request to handle individually.


Advantage
a. One of the advantage with mergemap is, it create single stream of observable and allows to process response of each request individually.
So if there is any request fails i.e. throws server side error, then it doesn't affect other parallel requests. Failed request(s) call error function in above code and succeeded request calls success function. (Which is advantage over second approach i.e. forkJoin function discussed below)

b. mergmap function start processing request as it get response i.e. in case of multiple parallel request it process request which completes first ,doen't wait for other request to get completed. (Which is advantage over second approach i.e. forkJoin function discussed below)

Disadvantage
a. It doesn't preserve sequence (i.e. order in which it fire) of requests, means if there are 10 request fired parallelly then which request complete first will display result first.

Solution to this is

    import { mergeMap, catchError } from 'rxjs/operators'; 
    list: Product[] = [];
    megeMapTest() {
    const prouctIds: number[] = [1, 2, 3];
    const requests = from(prouctIds)
      .pipe(
      mergeMap(id => this.productService.getProduct(id))
      );

      requests.subscribe(
      data => {
        this.list.push(data);

        this.list.sort((a: Product, b: Product) => {
          const aIndex = prouctIds.findIndex(id => id === a.Id);
          const bIndex = prouctIds.findIndex(id => id === b.Id);
          return aIndex - bIndex;
        });
      }, //process item or push it to array 
      err => console.log(err));
 } 

above solution code sort order of received response using index of array.

b. megeMap only merge request of same return type only. To understand this have look to above code again, all request is going to return observable of Product type which is going to be return by getProduct method of productservice.

Making use of forkJoin function can resolve this issue. Which is second approach discussed below.

2. ForkJoin

RxJs function forkJoin take one or more observable as input and provide steam of observable as result, which contains value last value emitted by each  inputted observable to function. Read more : forkJoin

import { catchError } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';
import { forkJoin } from 'rxjs/observable/forkJoin';
  forkJoinTest() {
    const prouctIds: number[] = [1, 2, 3];
    const productRequests = prouctIds.map(id => this.productService.getProduct(id).pipe(
      catchError(error => of(`Bad Promise: ${error.message}`))
    ));

    const requests = forkJoin(productRequests);
    requests.subscribe(
      data => console.log(data) //process item or push it to array 
    );
  } 

In above code, as per definition forkJoin takes observable requests as input and returns result.

Advantage
a. forkJoin  reserve sequence (i.e. order in which request sent), so order in which requests inputted to forkJoin in same order it gives response result.

b. forkJoin can take multiple request which returns different type observable.

async forkJoinTest() {
    const customerRequest =this.customerService.getCustomer(1).pipe(
      catchError(error => of(`Bad request: ${error.message}`))
    );    
    const orderRequest =this.orderService.getOrder(1).pipe(
      catchError(error => of(`Bad request: ${error.message}`))
    ); 
    const productRequest =this.productService.getProduct(1).pipe(
      catchError(error => of(`Bad request: ${error.message}`))
    );

    const requests = await forkJoin(customerRequest,orderRequest,productRequests).toPromise();
    
    console.log('Customer ' + requests[0]);
    console.log('order ' + requests[1]);
    console.log('product ' + requests[2]);
  } 

In above code , forkJoin takes three requests (customer, product, order) which returns different type of observable. Also code make use of async/await advance typescript/javascript concept, which allows to wait till request completes. (Which is advantage over first approach i.e. mergeMap function discussed below)

Disadvantage
a. forkJoin waits for all inputted Http requests to get completed before calling subscribe function. So even though some request get completed it has to wait till other or lets say last request to complete. (This can be avoided with mergeMap function as it process requests as it get completed).

b. if one of the inputted request to forkJoin fails , then forkJoin also fails and return error even other inputted request completed successfully. To check run code as below and return error from server

import { catchError } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';
import { forkJoin } from 'rxjs/observable/forkJoin'; 
  forkJoinTest() {
    const prouctIds: number[] = [1, 2, 3];
    const productRequests = prouctIds.map(id => this.productService.getProduct(id));

    //.pipe(
    //catchError(error => of(`Bad Promise: ${error.message}`))
    //));

    const requests = forkJoin(productRequests);
    requests.subscribe(
      data => console.log(data), //process item or push it to array
      err => console.log(err) 
    );
  } 

In above code catchError function is commented, that means if any of request fails then forkJoin also fails and return that error. (this is not case with mergeMap)
To avoid the make use of catchError function as given in above code.

Which one is better
Both of them is not good or not bad. It all depends on requirement at the end. Because there might be case when have requirement to wait for all request to complete or want to parallely executed request which return different value or do not want to produce result if one of sent requests fails then go for forkJoin and there might be case when have requirement for do not wait till all request get compete or do not want to reserve order of request or want to process requests even one of the request fails then go for mergeMap.  

Sunday, April 22, 2018

Angular Dependent Request

In software application, screen(s) where to display data application needs to make dependent request i.e. First have to make Request A (to server or database), based on result of A request data have to make Request B.

Example : In shopping application, on product screen , when user select product it will display product details and based on product make region it also display in which region it available or which region it's available.

So achieve in application there is need of dependent request , which works this way

  1.  It request (server/database) to get full product detail
  2. Based on product region , it makes request (server/database) to get available regions  

In code most of the developer write below code

this.productService.getProduct(1)
 .subscribe(data => {
          this.product = data;
          this.productService.getAvailableRegion(data.regionId)
                   .subscribe(region => this.avilableRegion = region);
}); 

code above does the task. But its complex (in terms of readability)  and not easy to understand when there is more depedent request are there  (if there are more dependent request like Request C , depends on Request B and which depends on Request A) as it goes deep and deep for each request.

Below are some way to avoid complexity and easy to understand code.

RxJs Way
Above example just make use of one RxJs function which subscribe, and does thing in that function only. For second request (dependent request) it does same thing which makes code complex. But RxJS provides number of functions apart of subscribe  which make things simple. Below is code how to reduce complexity of above code by making use of other function provided by Rxjs.

this.productService.getProduct(id)
  .pipe(
       map(data => this.product = data),
       switchMap (cust => this.productService.getAvailableRegion(this.product.regionId) )
   ).subscribe(region => this.avilableRegion = region); 

this does the same task as above code, but better way. Following functions to not down which makes code easy
  1. pipe - its RxJs function which allows number of RxJS function as input and combine them to perform operations one by one on observable received from previous function. 
    In above code it combines map and switchMap RxJs operator.
  2. map - it used to map returned observable value to other value. In this case it maps returned response to product.
  3. switchMap - it used for switching from one observable to other observable, in this example it switch from product to list of regions.
  4. Finally subscribe - this allows to subscribe to response observable stream of provided from pipe function after operation done in it.
Advance Typescript (async/await on Promise)

Another way to achieve same is make use of advance typescript concept , which making use of async/await. Below is code for the same

async getDetails(id) {
   this.product = await this.productService.getProduct(id).toPromise();
   this.avilableRegion = await this.productService.getAvailableRegion(this.product.Id).toPromise();
} 

Points to note with this approach is:

  1. async/await is used with Promise object only. 
  2. In code, promise object got created from returned observable by making use of toPromise method.

when method getDetails called from anywhere in code, executing stops when await keyword got encountered, and it waits till getProduct server request returns. Execution get resumed once server returned response which in this case return product. Then it stops execution again on encounter of await, which used to wait till availableResion request retuns.

At the End 

So there are two approach

  1. RxJs and 
  2. TypeScript 
none of them is better then another one , it all on developer preference. But both the way it makes code simple and easy to understand. It also help developer in maintaining code for long time as not much complexity involved. 


Saturday, March 31, 2018

Angular Custom Validation Component

Full Source at GitHub : AdvCustomValidationComponent

Validation is very important feature of application which allows to data entry (allows to enter data in application) as invalid data can leave application in inconsistent state, invalid date entry crash application and if data is not validated it can allows injection attacks on application. In Web application validation can be done at server side (i.e. on server like IIS, apache in language C#, PHP etc.) and at client side (i.e in browser windows using javascript).

Here, following post is about validation in Angular 2 application , which means its about validation on client side not about server side. Angular framework allows to do validation following two way
  1. Template Driven Form
  2. Reactive Form
One of this approach or mix of both approach can be used in application for validation. Not going to discuss about it as it provided in detail over here : Forms & Validation. But following post is going to discuss about custom component, which works with both the validation approach provide by angular 2 framework and encapsulate validation code in it.

Custom Validation Component
Let's first create validation component and make use of it in application. For fresh start of application follow this post : My first Angular 2 app - tutorial. After creating application create shared module in application by running below command in integrated terminal of visual studio code.
 ng g module shared.

Shared module is where custom validation component will resides , as custom validation component is dumb and its going to be used by multiple features in application. Run command on integrated terminal create
 ng g component shared/custom-input 
custom validation component.

custom-input.component.html
 <div class="form-group" >
  <label class="control-label">{{label}}</label>
  <br />
  <div [ngClass]="{'has-error':isError}" >
    <ng-content></ng-content>
    <ng-container *ngIf='isError'>
      <span class="text-danger" *ngFor="let msg of errorMessages"> {{msg}}</span>
    </ng-container>
  </div>
</div> 

Above is modification done in component html, some of the points to note in html are
  1. ng-content - which is very important tag in this html and important for validation component. This Angular 2 Framework tag allows to push any content in html when component loaded. For example:
    <custom-input>
      <input inputRef class="form-control" type="text" />
    </custom-input> 
    when above code written in component it will become like this,

    so input element put inside in ng-conent when component loaded in html page.
  2. inputRef its directive associated with input element, that intrun allows to access input element in comoponent typescript (more discussed below). 
  3. When custom component render in browser it look as below:

    So, html tags in component will create structure above as shown in below image 

    image above explain all the tags which made up component template. Just to note few points
    1. Border around the text box controls comes when text box becomes invalid. Border to textbox get applied by 'has-error' class , which get applied isError becomes true (in which case it becomes true described by code in typescript file below),
    2. "First Name Required"- this message comes when there is error i.e. in this image it error related to required validation. This passed as input to component described below
    3. label,(First Name) - will come from typescript associated with component template. This passed as input to component described below.
custom-input.component.ts
@Component({
  selector: 'custom-input',
  templateUrl: './custom-input.component.html',
  styleUrls: ['./custom-input.component.css']
})
export class CustomInputComponent implements OnInit {
  @Input() label: string;
  @Input() validations:  { [index: string]: string};
  @Input() info: string;

  @ContentChild(InputRefDirective) input: InputRefDirective;

  get isError() {
    return this.input.hasError;
  }

   get errorMessages() {
    const errors = this.input.errors;
    const messages = [];
    const keys = Object.keys(this.validations);

    keys.forEach(key => {
        if (errors[key]) {
          messages.push(this.validations[key]);
        }
      });
    return messages;
  }

  ngOnInit() { }

  constructor() { }
} 

Above is Component Typescript file , code in file handles all the backend logic to control Component invalid/valid state, putting red border around control when there is error and displaying error message when control is in invalid state.

Type Name Description
Input


label display label text for control E.x. First Name in above image

validations its indexed object hold validations associated with input tag of component
E.x. {'required' : 'First Name required', 'minlength': 'Minimum lenght is 3 char'}
Note: indexed property name must need to match with type of validation E.x. 'required' key match with required validation 

info
variable


input this component variable allows to get access to input control (which replaces ng-content in template of component) associated with component, for example above image in this case 'input textbox'.
Properties


isError component property which  find input element (with help of input directive) and get element has error or not, which in turn helps to put red border around input control

errorMessages component property which access errors associated input element (with help of input directive) and with help of input property validations object find proper error messages and return to display all. 

Important thing to not here is InputRefDirective , which access input control. Below is code for input-ref directive.

input-ref.directive.ts ( created by ng g directive directive/InputRef )
import { Directive } from '@angular/core';
import { NgControl } from '@angular/forms';

@Directive({
  selector: '[inputRef]'
})
export class InputRefDirective {

  constructor(private formControl: NgControl) {
  }

  get hasError() {
    return this.formControl.dirty && this.formControl.invalid;
  }

  get errors() {
    if (this.hasError && this.formControl.errors) {
      return this.formControl.errors;
    }
    return '';
  }
}

Important part of input-ref directive is, with help of constructor injection (by using angular framework injection) NgControl get injected in the input-ref directive. By doing that directive class get access to input control.

Type Name Description
Properties


hasError property return true (when control is dirty and invalid state) or flase , to indicate there is error or not

errors property returns list of errors associated with input control

So its end of creation of validation component and its related directive. Now let's see how to use it in application.

app.component.html
Reactive Form
<form class="needs-validation" [formGroup]="detailForm" novalidate>
    <custom-input [label]="'First Name'" [validations]="{required:'First Name required'}">
      <input inputRef class="form-control" formControlName="firstName" type="text" />
    </custom-input>
    <custom-input [label]="'Last Name'" [validations]="{required:'Last Name required'}">
      <input inputRef class="form-control" formControlName="lastName" type="text" />
    </custom-input>
    <div>
      <button [disabled]="detailForm.invalid" type="button" class="btn btn-primary">Primary</button>
    </div>
</form>

Component.ts for Reactive form only 
code below create form reactive way - point to note here no much code to access control and display error (discussed below in advantages).
export class AppComponent implements OnInit {
  title = 'app';
  detailForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.createForm();
  }

  ngOnInit() {
  }

  private createForm() {
    this.detailForm = this.fb.group({
      firstName: new FormControl('', [Validators.required]),
      lastName: new FormControl('', [Validators.required]),
    });
  }
}

Template Driven Form
<form class="needs-validation" #detailForm="ngForm" novalidate>
    <custom-input [label]="'First Name'" [validations]="{required:'First Name required'}">
      <input inputRef class="form-control" [(ngModel)]="firstName" name="firstName" type="text" />
    </custom-input>
    <custom-input [label]="'Last Name'" [validations]="{required:'Last Name required'}">
      <input inputRef class="form-control" [(ngModel)]="lastName" name="lastName" type="text" />
    </custom-input>
    <div>
      <button [disabled]="detailForm.invalid" type="button" class="btn btn-primary">Primary</button>
    </div>
</form>

It's not full template of application component code, but it part of template which uses Custom validation  component in both ways Reactive Form and Template Driven Form way. So not much change in both way, except change forced by reactive form approach and template driven form approach.

Not much in app.component template to discuss as already discussed before in post. app.component template make use of custom validation component and pass all required input values (label, info and validation error).

Below is image of final form after doing all changes



Advantage of using Custom validation component

  1. Less code in component template,
    Template driven from
     <label class="control-label">First Name</label>
      <input
      type="text"
      name="firstName"
      [(ngModel)]="firstName"
      minlength="2"
      required>
    
    <div *ngIf="firstName.errors?.required && firstName.touched && firstName.touched" 
    class="label label-danger">
      Name is required
    </div>
    <div *ngIf="firstName.errors?.minlength && firstName.touched && firstName.touched" 
    class="label label-danger">
      Minimum of 2 characters
    </div>

    Reactive from
     component.ts
    
     this.detailForm = this.form.group({
           firstName: [null, Validators.compose([Validators.required, Validators.minLength(2)])],     
        });
    
    component.html
    <label class="control-label">First Name</label>
    <inpu.
      type="text"
      name="firstName"
      [(ngModel)]="firstName"
      minlength="2"
      required>
    
    <div *ngIf="detailForm.get('firstName').errors?.required && detailForm.get('firstName').touched && detailForm.get('firstName').touched" 
    class="label label-danger">
      Name is required
    </div>
    <div *ngIf="detailForm.get('firstName').errors?.minlength && detailForm.get('firstName').touched && detailForm.get('firstName').touched" 
    class="label label-danger">
      Minimum of 2 characters
    </div>  

    If there is no custom validation component , in both the way (Template driven or Reactive way) one need to write down separate div for displaying each error input control has, for example (div for required error and div for minlength).
    But with custom validation control, there just need of passing validations in validations-property of control and it will take care of it.
        <custom-input [label]="'First Name'" 
                   [validations]="{required:'First Name required', 'minlength':'Minimum of 2 characters'}">
          <input inputRef class="form-control" [(ngModel)]="firstName" name="firstName" type="text" />
        </custom-input>
    

    Event there is no need to write extra label tag for displaying label for input control. This also taken care by custom validation control label-property.
  2. Second major difference is, custom validation control encapsulate code of validation in one place only for full application. That means there is no need to write validation code in template in each and every data entry form.

Wrapping up
Custom validation control is easy and simple to use. It makes use of some advance stuff like ng-content, directive to get input control under the hood and encapsulate thing in it. Once control included in application it reduce amount of validation code & effort to write validation code in every data entry form.
Full Source at GitHub : AdvCustomValidationComponent

Sunday, February 11, 2018

Extension method / Type Extension in TypeScript

During programming, most of the developers encounter scenario where there is need of adding behavior (method / operation) to existing type provide by framework (mostly by language) or into the type provided by third party library, which one can use in project multiple places without rewriting code again and again. And can access the extension code easily.

For example one want to extend Date Type and wants to add compareDate, so that it get attached to Date type as given in below image. just to note Date type is already provided Typescript language.


how to achieve behavior like that, answer is extension method.

Extension method
Extension method (programming language C# has this feature already) is way to extend existing type without modifying actual code file, means with help of the extension method one can add behavior (operation or method) without touching or modifying actual implementation file.
Now question arise how to create extension method, answer is by making use of Declaration Merging.

Declaration merging
Declaration merging in typescript allows to merge two declaration, for example if do like as below in typescript
 
interface User {
    name: string;
    id: number;
}

interface User {
    email: string;
}

and when create object of user as below


email is also part of User object as in above screen shot, it because of declaration merging. Compiler under the hood create User type as given below as it merge both the declaration of User interface defined above.
 
interface User {
    name: string;
    id: number;
    email: string;
}

Extension method on Date Type
So based on declaration merging, extension method can be added as below.

interface Date {
    compareDate(date: Date): number;
}

above code defined interface called Date with method name comparedate. So this will merge merge method called compareDate on existing Date type.
But above code just add method declaration without its implementation. Below is code which provide implementation of compareDate method.

Date.prototype.compareDate = function (date: Date) {
    if (this.toLocaleDateString() === date.toLocaleDateString()) {
        console.log('equal');
        return 0;
    }
    else if (this > date) {
        console.log('greater');
        return 1;
    } 
    else if (this < date)
    {
        console.log('less');
        return -1;
    }
}

so once implementation added , compareDate method get added to Date type of typescript and ready use. Below screen

Below is output of compareDate method.


Code to test
var date1 = new Date('4-3-2015');
var date2 = new Date('4-2-2015');

console.log(date1.compareDate(date2));

Sunday, December 17, 2017

Dynamic Html Structure with - *ngIf, *ngFor & ngSwitch

Directives in Angular Js 2 is used for structuring html document(DOM) (web page) and for changing behavior of html elements (Html page element like <input>, <form> etc.). Following kind of directive provided by angular js 2
  • Component – is most commonly used and most of the developer aware about it from the first day of development. One cannot start learning Angular js without learning it. It is only directive which comes with template attached with it. @Compnent is metadata value by which developer can make mark created directive is component. More at: https://angular.io/guide/displaying-data
  • Attribute – is directive which can change behavior of the element (html tag, component), with which is get attached as attribute. Most common attribute directive is ngModel, this allows bind element with the backend typescript object property, and provide (oneway-twoway) binding between model and view. @Directive is metadata value by which developer can make mark created directive is attibute directive. More at : https://angular.io/guide/attribute-directives
  • Structure – is type of directive which can change structure of html document. Directives are capable of adding-removing elements in html document. @Compnent is metadata value by which developer can make mark created directive is structure directive. More at : https://angular.io/guide/structural-directives
Angular js not only provide some build in directives but also provide way to create custom directives , find more at : https://angular.io/.

Not going in much details of directives , how to build them as post is focused on three most important structural directives *ngFor, *ngIf and ngSwitch & how to use them to build dynamic structure. Before jumping in lets understand this directives one by one

*ngIf – is in build directive which allows to show or hide element on page (i.e. to control display of element).

Example:
<div *ngIf=”IsShow” class="alert alert-danger"> Display Error!!! </div>
In example, IsShow is component model property which value get controlled by logic. For example : IsShow=true then is error and div get displayed or IsShow=false then is no error and div get hidden.

*ngFor – is in build directive to display element repeatedly on html page. It basically for loop on html document to create similar element on page but with different value and it works with Arrays of object (object can be user-defined class object or in build type object).

Example:
AppComponent.ts
export class AppComponent  {
  items:Array<number> = new Array<number>(1,2,3);
 }
Component.html
<ul>
  <li *ngFor="let item of items">
    {{item}}
  </li>
</ul>



<div *ngFor="let item of items">
    {{item}}
</div>



<select>
  <option *ngFor="let item of items" value="item">
    {{item}}
  </option>
</select>



In above example *ngFor works with Array of number and display all number repeating element. In 1. Case it displays list of 3 elements by repeating li element under ul, in 2. Case it displays 3 div element by repeatedly, In 3. Case it displays 3 option in select list.

Note:
*ngFor can decrease performance of your UI if not handled correctly.  Because *ngFor works with arrays and if any element removed from array or added in array, *ngFor remove all created element from DOM (html page) and recreate it with the new values.
So to avoid this behavior Angular team provided trackBy to this method to *ngFor directive to track changes.  It works as below

Example :
If model is like this

Employee.ts
export class Employee
{
  Id:number;
  Name:string;
  Designation: string;
  Department:string;
}
Then your html component html will be like as below with trackBy

AppComponent.html
<div *ngFor="let emp of employees; trackBy: trackEmployeeById">
  ({{emp.id}}) {{emp.name}}
</div>

And in your component.ts you have to add method for trackBy like as below.

AppComponent.ts
trackEmployeeById (index: number, emp: Employee): number { return emp.id; }
By adding trackBy Angular Js track element and do not recreate full structure when element get removed or added in array.

Index : like for loop *ngFor also allows access to index of element, one can access it as below
<div *ngFor="let item of items; let i=index">{{i + 1}} - {{item}}</div>
ngSwitch – is directive which is similar to switch statement in programming construct, it only emits element in Html page (DOM) when condition is matched.

Example:
AppComponent.ts
export class AppComponent  {

  items:Array<number> = new Array<number>(1,2,3,4);

 }
Component.Html 
 <div *ngFor="let item of items">
  <div ngSwitch="{{item}}">
    <div *ngSwitchCase="'1'">
      display 1 
    </div>
    <div *ngSwitchCase="'2'">
      display 2
    </div>
    <div *ngSwitchDefault>
      {{item}}-- display other element
    </div>
  </div>
</div>
As you see in above html, ngSwitch is similar to switch statement in programming language, similar to switch …case it also has ngSwitchCase. So when above html get executed then for array value 1 , it display 1 , value 2 it display 2 , for value 3 & 4 it displays  “3—display other element” & “4—display other element”.

Important note:
Important point to not here is, one cannot apply two Structural directives on one html element like as done in following code.
<div *ngIf="items.length>0" *ngFor="let item of items">
    {{item}}
</div>
So when above get executed following error get displayed on console of browser. Which says multiple template binding on one element.

It can be easily get resolved by doing as following
<div *ngIf="items.length>0">
  <div *ngFor="let item of items">
    {{item}}
  </div>
</div>
<ng-container>
But problem with above is one more div element get added in Html page (DOM). So to avoid it angular js provided <ng-container> element , which you can use as below

<ng-container *ngIf="items.length>0">
  <div *ngFor="let item of items">
    {{item}}
  </div>
</ng-container>
Now there is no extra div element get added on html page(DOM).  <ng-container> doesn’t affect structure of html page it used by angular js only just to note that it container which is having group of element under it.

Dynamic Structure with Structure Directives
Above is very simple and easy example with the structural directives, and it shows how you can easily achieve things in html without using line of javascript code, which developers are doing without angular js.
Now question may come how complex dynamic structure one can create with help of the structural directives ? to understand lets consider below example :

AppComponent.ts
export class AppComponent  {
  newTmpArr = [
    ["567", "2017-04-17T14:22:48", "45000", "button"],
    ["568", "2017-04-17T14:22:48", "45000", "button"],
    ["569", "2017-04-17T14:22:48", "45000", "link"],
    ["570", "2017-04-17T14:22:48", "45000", "button"]
  ];
 
  DoWork(ele:any)
  {
    //here you can do work , this get 
     //called when you press "click" button in table 
    alert(ele);
  }
}
For example, consider above data received by application component from external source like json File or from web service call.
Now requirement is as following
  1. Create html Table structure using this data structure
  2. Where ever property value is “button” html button needs to be get created &  when value is “link” html hyper link needs to be get created , and display other values as is as text element in html.
  3. Created link or button element must call function ”DoWork() (defined in script file above)” in script to process further.
Now if think of javascript, to achieve table structure with given data how many line of code needed. But in angular it can be done very easily

Component.Html
<table>
  <thead>
    <tr>
      <th>ID</th>
      <th>Date</th>
      <th>Ammount</th>
      <th>Action</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let ele of newTmpArr; trackBy: trackByIds">
      <td *ngFor="let val of ele">
        <ng-container ngSwitch="{{val}}">
          <ng-container  *ngSwitchCase="'button'">
            <input type="button" (click)="DoWork(ele)" value="click" />
          </ng-container>
          <ng-container *ngSwitchCase="'link'">
            <a href="#" (click)="DoWork(ele)">click</a>
          </ng-container>
          <ng-container *ngSwitchDefault>
            {{val}}
          </ng-container>
        </ng-container>
      </td>
    </tr>
  </tbody>
</table>
It display below output in html page

When button get click it display as below