·
Release:
AngularJS - 2010, Angular2 - 2016, Angular4 - 2017
·
Why
Angular2 over AngularJS?
o
AngularJS is based on Controller whereas Angular2 is based on Component, so angular2 provides features like modularity, reusability,
testability
o
Angular2 is five
times faster than AngularJS
o
Angular2 provides Mobile App development support
o
Angular2 provides more language choices like: JS, TS, Dart, PureScript, ELM etc.
·
Angular4
over Angular2
o
Angular4 is backward
compatible with Angular2
o
Angular4 has reduced compiler generated code
o
Animation
feature is pulled out from angular/core and moved to their own packages
o
We can use if-else
syntax using *ngIf in Angular4
·
Environment
setup for first sample app:
o
Install Visual Studio 2015, Node.js and
TypeScript for Visual Studio 2015
o
In Visual Studio, Click on Tools – Projects
& Solutions – External Web Tools: move $(path)
above, Web Tools/..External – ok
o
Create ASP.Net Empty Web Application
o
Download QuickStart from http://github/angular/quickstart
o
Copy, src, bs-config.json, package.json,
tslint.json and paste to root directory of new project
o
Include recently pasted files. Right click on
package.json and click Restore Packages
o
Open command prompt, navigate to root of project
and hit npm start command
·
Modification
to run above Angular project in Visual Studio using F5:
o
Index.html
§
base href = ‘/src/’
§
/shim.min.js
§
/zone.js
§
/system.src.js
o
Systemjs.config.js
§
‘npm’:’/node_modules/
o
Tsconfig.json
§
“CompileOnSave”:
true
·
Component
is a class with Template and Decorator in angular
·
Template defines
the User Interface, HTML and Data Bindings etc
·
Class contains
the code that is required for the template
·
Decorator
adds metadata to a class to make it is angular Component
·
Sample
Component
o
import {Component} from “@angular/core”
o
@Component({ selector:’selectorToAddComponent’,
Template: ‘HTML Template’})
o
export class ComponentName{
property = ‘value’; method(); }
·
Ways to
style a Component
o
External: Add styles in Style.css in root
directory
o
Inline: In Component HTML file in style
attribute
o
Internal: in Component HTML file within
<style> tag
o
Components Styles
property
o
Components StyleUrls
property
·
Interpolation
and Property Binding both are used
for one way data binding from Component class to template. Interpolation is simple
and convenient approach provided by angular, internally it does property
binding
o
Interpolation:
src = {{VariableThatHoldsValue}}
o
Property
Binding: [src] = ‘VariableThatHoldsValue’ or bind-src = ‘VariableThatHoldsValue’
·
If we have to set string value (concatenation) to the property, we must use
Interpolation. E.g.: innerHTML = {{‘Welcome’ + UserName}}
·
If we have to set non string value (Boolean)
to the property, we must use Property Binding. E.g.: [disabled] = ‘isDisabled’
·
Interpolation and Property Binding are used to
bind Class Properties to HTML Properties
not HTML attributes. To bind HTML Attributes, we use attr.AttributeNam. E.g.: attr.ColSpan = {{SpanValue}}
·
Properties Value can be changed but Attribute
Value cannot be changed. Attributes value used to initialize the HTML elements
·
Class
Binding is used to set CSS Class to HTML element. E.g.: [Class] = ‘VaribaleForClassName’. This will remove all existing styles
and add assigned classes to the HTML element. To keep existing classes as is
and to add/remove class, we can modify class binding as [class.ClassName] = ‘SetOrNotSetVariable’. For multiple class we use, [ngClass] = ‘ListOfClasses’; ListOfClasses = {Class1: true,
Class2: false ;…}
·
Style
Binding is used to set CSS style to an HTML element. E.g.: [style.styleName] = ‘styleValue’. Style property name can be written
in dash case or camel case. E.g.: font-size/
fontSize. Style that requires unit
value, can be set as: [style.fontSize.px] = ’size’.
[ngStyle] used for applying multiple styles to an HTML element similarly as
we use [ngClass]
·
Event
Binding is used for event handling and passing data from HTML element to
component class. E.g.: <button (click) = ‘onClickFunction()’> or <button (on-click) = ‘onClickFunction()’>. To get data from HTML element to component class we use (input) = ‘classVariable = $event.target.value’ or we can use [(ngModel)] = ‘classVariable’ for the same purpose. ngModel is combination of both event
binding and property binding so it is used for two way binding. To use ngModel,
we must import FormModule from angular/forms package in app module.
·
*ngIf
is a structural directive used to hide/show an HTML element depending on its
Boolean value. E.g.: <div *ngIf =
‘HideOrShow’>
·
*ngFor is
a structural directive used for repetitive HTML elements. E.g.: <tr *ngFor=’let employee of Employees;’> where Employees is a collection.
*ngFor provides following features:
o
let i
= index; //Returns the index of current record
o
let isFirst = first; //Returns TRUE
if it is first record
o
let isLast = last; //Returns TRUE if it is last record
o
let isEven = even; //Returns TRUE if it is even number record
o
let isOdd = odd; //Returns TRUE if it is odd number record
·
trackBy:
*ngFor is not suitable for large amount of records [performance issue] because
it recreates all HTML elements if the collection object is gets updates. To
overcome this issue, we use trackBy.
E.g.: <tr *ngFor=’let employee of employees; trackBy:TrckByEmployeeCode’ >..</tr> where
TrackByEmployeeCode(index, employee)
is a function which will return current employeeCode.
·
ng-container:
We cannot use multiple structural directive (e.g. *ngIf and *ngFor) in single
HTML element so to handle scenario where we need multiple structural directive
we can use ng-container.
·
E.g.: <ng-container
*ngFor=’CodeToIterateThroughCollection’>
<tr *ngIf=’ConditionToShowRecordOrNot’> </tr> </ng-container>
·
Pipes are
used for transform data before display. E.g.: {{variable | pipeName}}. We can use multiple pipes for
single HTML element. Angular provides following important pipes:
o
uppercase
/ lowercase
o
date : ‘format’ E.g.: dd/MM/yyyy, fulldate, shortdate, medium, longdate
o
currency
: ‘CurrencyName’ :
ShowCurrencySymbol : ‘MinDigits.MinDigits-MaxDigits’
·
We can have our custom pipe by implementing transform()
method of PipeTransform interface
o
import {
Pipe, PipeTransform } from ‘@angular/core’
o
@Pipe({
name: ‘NameOfThePipeToBeUsedInComponentHTML’ })
o
export
class ClasNameThatImplementCustomPipe implements
PipeTransform {
transform(value:string, additionalParameters : any){
//custom
code
}}
o
Include pipe in declaration of application
module
o
Use pipe in any component as: {{property
| pipename : parameterIfAny}}
·
Nested
/Child Component is a component that is included into another component. To
nest a component, include the selector of child component into the HTML
template of parent as directive.
·
Input
Property is used to get data from parent component. Steps to use Input
Property:
o
In child Component: import {Input} from ‘@angular/core’;
o
Decorate class property with @Input() to make it as Input Property.
E.g.:
@Input()
ParentValue: string;
o
In parent template: <childSelector [PropertyName] = ‘ValueToPass’> E.g.:
<EmployeeDetails [Total] =
‘getTotalEmployeeCount()’>
·
Output
Property is used to send data to parent component. We can pass event
handler to parent component to handle event at parent component as below:
o
In child component: import {Output, EventEmitter } from ‘@angular/core’;
o
Create event handler using EventEmitter class
and mark it as Output property as:
@Output()
myEventHandler : EventEmitter<EventPayload/ parametersToPass>
= new EventEmitter<EventPayload/
parametersToPassToParentComponent>();
o
Emit handler from child event as:
functionCalledFomChildComponent(){
this.myEventHandler.emit(parametersToPassToParentComponent);
}
o
In parent template assign parent function to
child output property/event handler as:
<ChildComponent (ChildEventHandler) = ‘ParentFunction($event)’></ChildComponent>
·
Interface:
TypeScript is strongly typed language so generally we use string, number,
boolean etc predefined data types but if we want a user defined custom data type
then we can use Interface. We can declare interface as: export interface InterfaceName{} and use as : className implements InterfaceName
·
Short-Hand-Syntax
used to initialize properties in constructor as: constructor(AccessModifier
propertyName: DataType){}. E.g constructor(private
_employeeName: string){}
·
Angular
Component Lifecycle Hooks: methods which can be used as lifecycle event.
o
ngDoCheck
o
ngComponentInit, ngComponentChecked
o
ngViewInit, ngViewChecked
o
ngOnChanges
called every time the value of a class property change. This provides us old & new value of the
property
o
ngOnInit called
only first time after ngOnChanges and constructor. Generally used for component
initialization, data retrieval etc.
o
ngOnDestroy
called on component destruction. Generally used for cleanup code.
·
How to
use lifecycle hooks:
o
Import {OnChanges} from ‘@angular/core’;
o
Import {SimpleChanges} from ‘@angular/core’; // required for OnChanges
o
export
class ClassName implements OnChange{} //writing implements is optional here
o
implement OnChanges as:
ngOnChanges(changes: SimpleChanges){
for(let propertyName in
changes){
let
change = changes[propertyName];
let
current = JSON.Stringyfy(change.CurrentValue);
let
previous = JSON.Stringify(change.PreviousValue);
}
}
·
Angular
Services are used when we want to reuse data across multiple components. We
can write service as below:
o
import
{Injectable} from ‘@angular/core’
o
decorate class by @Injectable() to inject dependency in service
o
export
class ServiceName {}
o
Add functions that you want to expose from
service e.g.: getEmployees(){}
·
We can access angular services as below:
o
import {ServiceName} from ‘./AngularServicePath’
o
create object of service as: constructor( private _service: ServiceName){}
o
Register service using [provider] directive either in @Component({}) or in @module({})
·
Usually services are called from ngOnInit() hook
not from constructor to not to make page busy.
·
How to
call API from angular:
o
In root module, import { HttpModule } from ‘@angular/http’;
o
Include HttpModule in imports[] of root module
o
In service class, import { Http } from ‘@angular/http’;
o
Create instance of Http: constructor(private _http: Http){}
o
Now we can use _http (instance of Http) to call API using GET, PUT, POST etc functions.
o
These functions returns Observable<Response>
which we need to handle as per our requirement using map (to handle response)
and subscribe (to handle callbacks).
·
Example
to call API:
o
Import {
Injectable} from ‘@angular/core’;
o
Import {
Http, Response } from ’@angular/http’;
o
Import {
Observable } from ‘rxjs/observable’;
o
Import ‘rxjs/add/operator/map’;
o
@Injectable()
o
Export class
TestService {
o
Constructor
(private _http: Http){}
o
TestServiceMethod
() : Observable<any>{
o
return this._http.get(‘ServiceURL’).map((response: Response) => <any>resonse.json()); }
·
Observable
is an async pattern in which:
o
Observable,
emits data and notify / executes callback function.
o
Observer/
Subscriber, subscribes to observable with callback function.
o
One observable
can have multiple subscriber
o
We can subscribe service from any component as:
o
this.ServiceName.ServiceMethodName(ParamsIfAny).subscribe((data)=>{ // some code });
·
Subscribe
method has following three parameters:
o
OnNext: This
function executes once data emitted by observable
o
onError: This function executes if any error occurred
o
onComplete:
This function will be called after all data is emitted i.e. it executes
after onNext for the final item
·
Error
Handing in service is done by using catch/throw
operator of rxjs as below:
o
Import ‘rxjs/add/operator/catch’;
//we can use throw as well
o
In service call, this._http.get(‘URL’).map(…).catch(errorHandlerFunction);
o
E.g.
errorHandlerFunction(error: Response){
o
return Observable.throw(error);
} //This will throw error to
subscriber
o
In subscriber,
this.ServiceName.ServiceMethodName().subscribe(SuccessCallback, (error) => ErrorCallback(error));
// Here we can handle error as per requirement
·
Retry
in observable is used to recalling the
service in case of error as below:
o
Import ‘rxjs/add/operator/retry’;
o
In subscriber component, this.ServiceName.ServiceMethod().retry(RetryCount)subscribe(…);
//If RetryCount is not mentioned it will try infinitely
·
RetryWhen
in observable is used when we want to
recall a service after some delay or on some condition. We can use it as
below:
o
Import ‘rxjs/add/operator/retrywhen’;
o
Import ‘rxjs/add/operator/delay’;
o
Import ‘rxjs/add/operator/scan’;
o
In subscriber component, this.ServiceName.ServiceMethod().retrywhen((error)=>error.delay(1000))subscribe(…); //This will retry
calling service (in case of error) after I second (1000 milliseconds)
o
We can use scan()
of error to get the details of retry
in retrywhen as:
retryWhen((error)
=> {
return error.scan((retryCount) => {
retryCount += 1;
if(retryCount < 6)
return retryCount;
else
throw error; }); });
·
Unsubscribe
in observable is used cancel the retry/
recall service as below:
o
Import {
ISubscription } from ‘rxjs/subscription’;
o
Create instance of IScubsciption, private _subscription: ISubscription;
o
Set subscriber instance, _subscription = this.ServiceName.ServiceMethod().subscribe(…);
o
In function where we want to unsubscribe, this._subscription.unsubscribe();
o
_subscribe.closed property used to get the status
of subscription.
·
We can use Promise
instead of Observable as:
o
Import ‘rxjs/add/operator/toPromise’;
o
serviceMethod() Promise<any>{
o
return
this._http.get(‘URL’).map(…).toPromise().catch(promiseErrorHandler);}
o
Error
Handling in observable:
§
Observable.throw(error);
o
Error
Handling in Promise:
§
throw (error)
o
In service calling component, this.ServiceName.ServiceMethod().then(…).catch(…);
·
Promse vs
Observable:
o
Promise
emits single value, observable emits multiple values over period of time
o
To call service:
§
.then(successCallback,
errorCallback);
§
Subscribe(onNextCallback,
onErrorCallback, onCompleteCallback);
o
Promise is
not lazy, observable is lazy. Observable is not called until we subscribe
the observable. If we don’t have subscribe() then service is not called but even if we don’t have then() still service
gets called.
o
Promise
cannot be cancelled. Observable can be cancelled using unsubscribe()
o
Observable provides different operators like:
map, forEach, filter, retry, retryWhen, reduce, unsubscribe.
·
Routing
is used to navigate from one view/component to another as below:
o
In root module, import {RouterModule, Routes} from ‘@angular/router’;
o
Declare RouteModule in imports[] of root module
o
Declare routing path as:
§
const
appRoutes:
Routes = [
§
{path:
’pathOne’, component: componentName}, //Normal Route
§
{path:
‘pathTwo/:param’, component: ComponentName}, //with param as parameter
§
{path:
‘’, redirectTo:’/SomePath’, pathMatch: ‘full’}, //Empty Route
§
{path:
’**’, component: pageNotFoundComponent}];
//Invalid Route
o
Set routes as: imports[RouteModule.ForRoot(appRoutes,
{useHash=true})]
o
Use routerLink
attribute to navigate from component HTML. <li
routerLink=’Home’>
o
Use <router-outlet></router-outlet>
as placeholder for routed component
o
If we don’t use hash style routing and use
default HTML5 routing then we need to add re-write rule in web.config as:
§
<system.webServer><rewrite><rules>
§
<rule name=’RuleName’ stopProcessing=’true’>
§
<match url=’.*’ />
§
<conditions logicalGrouping = “MatchAll”>
§
<add input=”{REQUEST_FILENAME}” matchType=”IsFile”
negate=”true” />
§
<add input=”{REQUEST_FILENAME}” matchType=”IsDirectory”
negate=”true” />
§
</conditions><action type=”Rewrite”
url=”/src/” /> </rule></rules></rewrite>…
o
routeLinkActive=’activeClassName’ attribute is used to set a class if RouteLink is active
o
To set routingLink
with parameter: <a routerLink=”[‘/Home’,
pram]”> where first parameter is path
of route and second parameter is
parameter to route
o
Read route
parameter from URL:
§
import {
ActivatedRoute } from ‘@angular/router’;
§
constructor(private
_activeRoute: ActivatedRoute){}
§
this._activeRoute.Snapshot.params[“parameterName”]
o
navigate()
method used to navigate to a route as
:
§
import {
Router } from ‘@angular/router’;
§
constructor
(private _router: Router) {}
§
this._router.navigate([‘/Home’]);
·
Dependency
Injection is a coding pattern in which a class receives a dependency from
an external source rather than creating itself. For example, to use angular
service we use constructor(private _serviceObject: ServiceName){} this short hand syntax, but we don’t
see new() which actually creates the
object. Here Angular Injector
creates/ provides the singleton object of the service to us and to know the
injector about dependency we register service in component/ module using [provider].
·
Why dependency
injection? Before DI, we need to create object of service explicitly, which
has following drawbacks:
o
Difficult
to maintain: if service constructor definition change then we needs to
update it everywhere it is used. In case of DI we are not explicitly creating
object.
o
Sharing:
Instance created by class is local to that class so we cannot share data and
logic across components
o
Difficult
to Unit Test
·
Getter
and Setter in TypeScript:
o
get propertyName(): returnType
{ return privateVariableValue; }
o
set propertyName(value: DataType) { privateVariable = value; }