Angular-13 Full
Angular-13 Full
Angular-13 Full
https://nodejs.org/en/
[Windows 8+, any another OS]
C:\>node -v 12+
C:\>npm -v 6+
https://code.visualstudio.com/
D:\TypeScript-Project
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
<script src="../src/index.js"></script>
</head>
<body onload="bodyload()">
<h2>Welcome to TypeScript</h2>
<div id="container"></div>
</body>
</html>
- Variables
- Data Types
- Operators
- Statements
- Functions
Variables
- Variables in Typescript are same as in JavaScript.
- Variables are declared by using
a) var
b) let
c) const
- Variables in typescript are strongly typed.
Syntax:
var variableName:dataType;
Ex: JavaScript
var x = 10; // x is number
x = "A"; // x is string
x = true; // x is boolean
Data Types
- Primitive Types
a) number
b) boolean
c) string
d) null
e) undefined
- Non Primitive Types
a) Array
b) Object
c) Map
Syntax:
let username = "john"; // type is string
let age = 22; // type is number
Syntax:
let username:string | number;
username = "john"; // valid
username = 1001; // valid
username = true; // invalid
Ex:
1. Write the following code into "Index.ts"
console.log(`Name=${ProductName}\nPrice=${Price}\nStock=${(Stoc
k==true)?'Available':'Out of Stock'}`);
Summary :
========
1. number
2. string
3. boolean
4. null
5. undefined
let variableName:number;
let variableName:string | number;
let variableName:any;
Non-Primitive Types
===============
1. Array
2. Object
3. Map
JavaScript:
let collection = [ ];
let collection = new Array();
Array Methods:
join(), slice(), splice(), indexOf(), lastIndexOf(), pop(), push() etc
TypeScript Array
=============
- You can design array in typescript to handle similar type of values or
with combination of various types of values.
Syntax:
let collection:string[] = [ ]; // only string
let collection:number[] = []; // only number
Syntax:
let collection:any[] = [10, 'john', true]; // valid
let collection:any[] = new Array(10, 'john'); // invalid
only number.
let collection:any[] = new Array('john', 10); // invalid
only string.
Syntax:
let collection:any[] = new Array();
collection[0] = 10;
collection[1] = 'john'; /// valid
Syntax:
let collection:string[] | number[] = [10, 'john']; // invalid
Syntax:
let collection: any[] = [ ];
Reading
- toString()
- join()
- slice()
- find()
- filter()
- map()
Add
- push()
- unshift()
- splice()
Remove
- pop()
- shift()
- splice()
Ex:
let categories:string[] = ['All', 'Electronics', 'Footwear'];
categories.push('Fashion');
categories.map(function(value){
console.log(value);
})
Object, Maps
https://github.com/Sharma-NareshIT/angular13
Syntax:
let obj:any = { };
Ex:
let product:any = {
"Name": "Samsung TV",
"Price": 56000.44,
"Stock": true,
"ShippedTo": ['Delhi','Hyd'],
"Qty":2,
"Total":function(){
return this.Qty * this.Price;
},
"Print":function(){
console.log(`Name=${this.Name}\nPrice=${this.Price}\nStock=${this.S
tock}\nQty=${this.Qty}\nTotal=${this.Total()}\nShippedTo=${this.Ship
pedTo}`);
}
}
product.Print();
Syntax:
let products:any[] = [ { }, { }, { }, ... ];
Ex:
let products:any[] = [
{Name: 'TV', Price:56700.44},
{Name: 'Mobile', Price: 45000.33}
];
console.log(`Mobile Price=${products[1].Price}`);
Syntax:
let data:any = new Map();
data.set()
data.get()
data.delete()
data.clear()
Ex:
let products:any = new Map();
products.set(1, 'Samsung TV');
products.set(2, 'Mobile');
console.log(products.get(2));
Object:
- It is a key and value collection.
- Keys are only string type.
- No size for Keys
- You need explicity iterators to read keys and values.
- It is slow in reading and rendering.
Map:
- It is also a key and value collection.
- Keys are configured with any type.
- You can configure size for keys
- Map provides implicit iterators for reading keys and values.
[keys(), values(), entries()]
- It is faster in reading and rendering.
Ex:
let products:any = new Map();
products.set(1, 'Samsung TV');
products.set(2, 'Mobile');
console.log(products.get(2));
getHours()
getMinutes()
getSeconds()
getMilliSeconds()
getDay()
getDate()
getMonth()
getFullYear()
Ex:
let Manufactured:any = new Date('2022-01-18');
console.log(`Manufactured Year=${Manufactured.getFullYear()}`);
Ex:
let password:string = 'JOHN';
let regExp:any = /[A-Z]{4,10}/;
if(password.match(regExp)) {
console.log('Password Verified..');
} else {
console.log('Error: Password 4 to 10 chars Uppercase Only');
}
Summary:
- handling various data types
number
string
null
boolean
undefined
array
object
map
regular expression
date
array of object
let name:number[ ] = [ ]
let name:any[] = [];
let exp:any = / /;
Typescript OOP
- TypeScript is an OOP language.
- It supports all features of OOP.
Contracts in OOP
- Contract defines rules for designing a component in OOP.
- Contracts are designed by using "interface".
Syntax:
interface InterfaceName
{
// rules
}
Ex:
interface ProductContract
{
Id:number;
Name:string;
Cost:number;
Stock:boolean;
}
let product:ProductContract = {
"Name": "Samsung TV",
"Cost": 56000.44,
"Stock": true,
"Id": 1,
}
Contracts in OOP
- Contract defines rules for designing any component in OOP.
- Contracts are defined by using "interface"
- Interface can contain only declaration.
Syntax:
interface Name
{
}
Ex:
interface ProductContract
{
Id:number;
Name:string;
Cost:number;
Stock:boolean;
}
let product:ProductContract = {
"Name": "Samsung TV",
"Cost": 56000.44,
"Stock": true,
"Id": 1,
}
Optional Rules in Contract:
- Every rule defined in contract is mandatory
- TypeScript contract can configure optional rules.
- Optional rules are required to design goal of any module or
component.
- Mandatory rules are required to configure the objective of
component.
- You can configure optional rules by using
"null reference character - ?"
Ex:
interface ProductContract
{
Id:number;
Name:string;
Cost:number;
Stock?:boolean; // optional
}
let product:ProductContract = {
"Name": "Samsung TV",
"Cost": 56000.44,
"Id": 1,
}
Syntax:
interface Name
{
readonly Property:dataType;
}
Ex:
interface ProductContract
{
Name:string;
readonly Price:number;
}
let tv:ProductContract = {
Name : "Samsung TV",
Price: 56000.55
}
tv.Name = "Samsung LED TV";
tv.Price = 70000.55; // invalid - readonly
console.log(`Name=${tv.Name}\nPrice=${tv.Price}`);
Syntax:
interface Name
{
method():dataType;
method?():void;
}
Ex:
interface ProductContract
{
Name:string;
Price:number;
Qty:number;
Total():number;
Print?():void;
}
let tv:ProductContract = {
Name : "Samsung TV",
Price: 56000.55,
Qty: 2,
Total() {
return this.Qty * this.Price;
},
Print() {
console.log(`Name=${this.Name}\nPrice=${this.Price}\nQty=${this.Qt
y}\nTotal=${this.Total()}`) ;
}
}
tv.Print();
Extending Contracts:
- Every contract is configure with set of rules.
- You can extend the contract without modifying the existing set of
rules and contract.
- A contract can be extended by using "extends" keyword.
- Contract supports extending
a) Single
b) Multiple
c) Multi Level
interface A
{
}
interface B extends A
{
}
interface D extends A, B, C
{
}
Ex:
interface ECMA2015
{
Operators:string;
Parameter:string;
}
interface ECMA2016 extends ECMA2015
{
Functions:string;
}
interface ECMA2017 extends ECMA2016
{
OOP:string;
Functions:string;
}
let JavaScript:ECMA2017 = {
Parameter : '',
Operators: '',
OOP: '',
Functions: ''
}
Ex:
interface TextEffects
{
Align:string;
}
interface BackEffects
{
BgColor:string;
}
interface Effects extends TextEffects, BackEffects
{
Border:string;
}
let css : Effects = {
Align : 'center',
BgColor: 'red',
Border : '2px solid red'
}
TypeScript Class
Class in OOP
- Configuring class is similar to JavaScript
- Class members also same
a) Properties
b) Methods
c) Accessors get(), set()
d) Constructor
- TypeScript class supports 2 types of members.
a) Static Member
b) Non Static Member
What is static?
- Static refers to contineous memory.
- Memory allocate for first object will continue for next object.
- It uses more memory
- It can lead to memory leaks.
- Burden for application
- TypeScript static members are defined by using "static" keyword
- Static members are accessible within the class or outside class by
using class name.
Syntax:
class className
{
static s = 0;
}
className.s ;
What is non-static?
- It refers to discreet memory.
- It uses disconnected memory.
- Memory is newly allocated for every object.
- Non static members are accessible within the class by using "this"
keyword and outside the class by using instance of class.
Syntax:
class Name
{
n = 0; // non-static
static s =0; // static
this.n;
}
let obj = new Name();
obj.n;
Ex:
class Demo
{
static s = 0;
n = 0;
constructor(){
Demo.s = Demo.s + 1;
this.n = this.n + 1;
}
Print(){
console.log(`s=${Demo.s} n=${this.n}`);
}
}
let obj1 = new Demo();
obj1.Print();
let obj2 = new Demo();
obj2.Print();
let obj3 = new Demo();
obj3.Print();
public member:
- It is public in access.
- It is accessible from any location and through any object reference.
- It is the default access modifier for members in TypeScript class.
- You can access by using base class object or derived class object.
- You can access in base or in derived class.
- You can access within the class or outside class.
private member:
- It is private in access.
- You can access only within the defined class.
- It is not accessible outside class.
protected member:
- It is protected in access.
- You can access with in the defined class.
- You can access outside class only with in dervied class by using
derived class object.
- It is protected for derived members.
Summary
access public private protected
--------------------------------------------------------------------------------------------
----
with in class yes yes yes
Ex:
class Product
{
public Name:string = 'Samsung TV';
private Price:number = 45600.55;
protected Stock:boolean = true;
public Print():void{
console.log(`Name=${this.Name}\nPrice=${this.Price}\nStock=${this.S
tock}`);
}
}
class ProductExtention extends Product
{
public Print(): void {
let obj = new ProductExtention();
obj.Name;
obj.Stock;
}
}
class Base
{
constructor(){
}
}
class Derived extends Base
{
constructor() {
super();
}
}
Templates in OOP
- A template comprises of sample data and logic, which you can
implement and customize according to the requirements.
Syntax:
interface IName
{
}
class className impements IName
{
}
- If a class contains at least one abstract member then the class must
be marked as "abstract".
Syntax:
abstract class Template
{
public Name:string = ' ';
public abstract Total():number;
}
Note:
1. A contract can extend another contract.
2. A class can implement contract.
3. A class can implement multiple contracts.
4. A class can extend another class.
Ex:
interface ProductContract
{
Name:string;
Price:number;
Qty:number;
Total():number;
Print():void;
}
interface CategoryContract
{
CategoryName:string;
}
abstract class ProductTemplate implements ProductContract,
CategoryContract
{
public Name: string = '';
public Price: number = 0;
public Qty: number = 0;
public CategoryName: string = '';
public abstract Total():number;
public abstract Print(): void;
}
//------------------------- Developer Implements --------------------------
console.log(`Name=${this.Name}\nPrice=${this.Price}\nQty=${this.Qt
y}\nTotal=${this.Total()}`);
}
}
Module System
- Export
- Default
- Import
CommonJS
Require JS
UMD
AMD
Ex:
1. Add a new folder "library"
2. Add sub folders
- contracts
- templates
- components
3. contracts
ProductContract.ts
export interface ProductContract
{
Name:string;
Price:number;
Qty:number;
Total():number;
Print():void;
}
4. templates
ProductTemplate.ts
5. components
ProductComponent.ts
import { ProductTemplate } from "../templates/ProductTemplate";
console.log(`Name=${this.Name}\nPrice=${this.Price}\nQty=${this.Qt
y}\nTotal=${this.Total()}`);
}
}
Syntax:
Method<Type>(Param:Type) : Type
{
}
Method<string>(Param:string): string;
Method<number>(Param:number):number;
Add<T>(a:T, b:T):T
{
return a + b; // invalid
return sum(a,b); // valid
}
function Sum(a:any,b:any) {
return a + b;
}
class Demo
{
public Add<T>(a:T, b:T):T{
return Sum(a,b);
}
}
let obj = new Demo();
console.log(obj.Add<string>("Tom", "Hanks"));
console.log(obj.Add<number>(20,50));
Syntax:
Method<T>(param:T)
{
}
Method<Contract>(param:Contract);
Method<Class>(param:Class);
Ex:
interface IOracle
{
UserName:string;
Password:string;
Database:string;
}
interface IMySql
{
host:string;
user:string;
password:string;
database:string;
}
interface IMongoDB
{
url:string;
}
class SqlServer {
UserId:string = 'Server';
Password:string = '12345'
}
class Database
{
public Connection<T>(connectionString:T){
for(var property in connectionString) {
console.log(`${property} :
${connectionString[property]}`);
}
}
}
console.log(`---------Connection to Oracle---------`);
let oracle = new Database();
oracle.Connection<IOracle>({UserName:'scott',
Password:'tiger', Database:'empdb'});
console.log(`---------Connection to MySql----------`);
let mysql = new Database();
mysql.Connection<IMySql>({host:'localhost', user:'root',
password:'1234', database:'productsdb'});
console.log(`---------Connection to MongoDB---------`);
let mongo = new Database();
mongo.Connection<IMongoDB>({url:'mognodb://127.0.0.1:2701
7'});
console.log(`---------Connection to SqlServer-----`);
Syntax:
Method<T>(param:T) { }
Method<IProduct[]>([]);
Ex:
class Factory<T>
{
public FirstName:T|undefined;
public LastName:T|undefined;
}
Enums
[Enumeration]
- Enum is a collection of constants.
- It is a key value collection of constants.
- Enum can have collection of number, string and expression
constants.
- A constant is used to initialize values, constant values will not
allow assigning of values.
Syntax:
enum Name
{
Syntax:
enum Name
{
A = 10,
B
}
Name.B // 11
Syntax:
enum Name
{
A, // 0
B=10
}
Ex:
enum StatusCode
{
Method,
NotFound = 404,
OK = 200,
Unauthorized,
}
console.log("Method=" + StatusCode.Method); // 0
console.log("Unauthorized=" + StatusCode.Unauthorized); //
201
Ex:
enum Route
{
Electronics, // 0
Home = 'http://localhost/app/home HYPERLINK
"http://localhost/app/home&"& HYPERLINK
"http://localhost/app/home&"#39;,
Contact = 'http://127.0.0.1/app/contact?address HYPERLINK
"http://127.0.0.1/app/contact?address&"& HYPERLINK
"http://127.0.0.1/app/contact?address&"#39;,
Fashion = 200
}
console.log(Route.Home);
Syntax:
enum Name
{
A = 'string',
B // invalid
}
- Enum can have collection of expressions, but only the
expressions that return a number or string.
- Boolean expressions are not allowed in Enum.
Ex:
enum Calculate {
A = 10,
B = 20,
C = A + B,
D
}
console.log(`D=${Calculate.D}`);
Syntax:
let name = EnumName[value];
Ex:
enum StatusCode
{
NotFound = 404,
}
let ErrorCode = StatusCode[StatusCode.NotFound];
console.log(`Error Reference: ${ErrorCode}`);
console.log(`Error Code: ${StatusCode.NotFound}`);
- We can also use enum as a type.
Syntax:
enum HttpVerbs
{
GET = 'Fetch Data',
POST = 'Submit Data',
PUT = 'Modify Data'
}
let obj = 'GET' as HttpVerbs;
obj:HttpVerbs;
Ex:
• Add a new folder
Project
1. Add following folders into project folder
- Contracts
- Templates
- Services
- App
2. Add following file into contracts
“ProductContract.ts”
namespace Project
{
export namespace Contracts
{
export interface IProduct
{
Name:string;
Price:number;
Qty:number;
Total():number;
Print():void;
}
}
}
namespace Project
{
export namespace Services
{
export class Product extends templates.ProductTemplate
{
public Name:string = '';
public Price:number = 0;
public Qty:number = 1;
public Total():number {
return this.Qty * this.Price;
}
public Print():void {
console.log(`Name=${this.Name}\nPrice=${this.Price}
\nQty=${this.Qty}\nTotal=${this.Total()}`);
}
}
}
}
MyApp.ts
Compile
> tsc --outFile myapp.js myapp.ts
- Single Ton
It is a software design pattern where object is created for
first request and same object is used for all other requests.
What is a service?
- It is a predefined bussiness logic which is injected into
application to handle specific operation
- Service is a set of factories.
- Service depends on 2 components
a) Provider
b) Injector
- Provider is responsible for locating service in memory.
- Injector is responsible for injecting service into component.
Ex:
1. Add services folder and a new file
"DataService.ts"
export class DataService
{
public GetProducts(){
return [
{Name: 'TV', Price:56000.44},
{Name: 'Mobile', Price: 12000.44}
];
}
public GetCategories(){
return [
'Electronics', 'Footwear', 'Fashion'
];
}
}
}
public PrintProducts(){
console.log(`----Products List------`);
for(var product of this.data.GetProducts()) {
console.log(`${product.Name} - ${product.Price}`);
}
}
public PrintCategories(){
console.log(`----Categories List-----`);
for(var category of this.data.GetCategories()) {
console.log(category);
}
}
}
Summary:
- Single Call
- Single Ton
- Factory
- Service
- Provider
- Injector
Angular
- Angular is a developers platform.
- A developers platform provides end to end solution for
developer i.e from building to deploying.
- Angular is alternative for Angular.js
- Angular is cross platform, open source framework suitable for
building SPA.
- Angular is mantained by Google and a large community of
developers and organizations.
- Angular started with 2.0 version
- Angular latest is 13.2.2 [stable]
- Angular Versions upto 12 LTS previous versions no-longer
supported.
Features of Angular
1. Developer platform
2. Modular Library
- Application specific framework.
- Faster
- Light weight
- Suitable for low bandwidth devices
3. Differential Loading
- Reduces the compatibility issues
- Loads legacy library for legacy browsers
and loads modern library for modern browsers
4. Asynchronous
- Implicitly uses Ajax for various interactions
- Improves the perfomance of application.
2. Clear Cache
www.editorconfig.org
D:\my-angular-workspace>
http://localhost:4200
- Install Angular
> npm install @angular/cli -g
- Create Workspace
- Create Application
- To start application
http://localhost:4200
Resources of "app"
===============
1. Angular Framework comprises
- Modules
- Components
- Services
- Factories
- Templates
- Pipes
- Routing
- State Management [Client Side]
Angular Components
=================
- Components are building blocks for Angular Application.
- Application is built by using components.
- A component comprises of
a) Presentation
b) Styles
c) Functionality
Issues
- Hard to test
- Separation concerns
- Hard to Extend
When to use?
-If you need a component with stable functionality and design
without regular extensions then go with inline technique.
Designing Component
=================
1. Technically component is designed in a typescript file.
2. Component is a class.
a) selector
b) template
c) styles
Syntax:
template: `<markup> {{ expression }}</markup>`
Syntax:
styles: ['selector{attribute:value}']
@NgModule( {
declarations : [ ComponentName ]
})
@NgModule({
bootstrap: [ ComponentName ]
})
8. Go to Index.html and use the selector to render component
in body section
<body>
<app-home> </app-home>
</body>
Ex:
1. Add a new folder by name "components" into "app" folder
@Component({
selector: 'app-home',
template: `
<h2>{{title}}</h2>
<p>Online Shopping Application</p>
`,
styles:['h2{text-align:center; background-color:tomato;
color:white}']
})
export class HomeComponent
{
title:string = 'Shopping Home';
}
3. Go to "app.module.ts"
bootstrap: [HomeComponent]
4. Go to Index.html
<body>
<app-home> </app-home>
</body>
Angular Components
- Manually Add component using Inline Technique
- Manually Add component using Code Behind Technique
Ex:
1. Goto "app/components" folder
2. Add a new folder "register"
3. Add the following files
register.component.ts
register.component.html
register.component.css
templateUrl: './html_file_path'
styleUrls: ['./css_file_path']
selector : 'app-component'
register.component.ts
-----------------------------
import { Component } from "@angular/core";
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent
{
title:string = 'Register User';
}
register.component.html
--------------------------------
<div id="container">
<form>
<h3>{{title}}</h3>
<dl>
<dt>User Name</dt>
<dd><input type="text"></dd>
<dt>Password</dt>
<dd><input type="password"></dd>
<dt>Email</dt>
<dd><input type="email"></dd>
</dl>
<button>Register</button>
</form>
</div>
register.component.css
-------------------------------
#container{
display: flex;
justify-content: center;
align-items: center;
height: 400px;
}
form {
padding: 20px;
border:2px solid gray;
border-radius: 20px;
}
<app-register> </app-register>
@import '../../../node_modules/bootstrap/dist/css/bootstrap.cs
s';
@import '../../../node_modules/bootstrap-icons/font/bootstrap-
icons.css';
- Go to "register.component.html"
<div id="container">
<form>
<h3><span class="bi bi-person-fill"></span> {{title}}</h3>
<dl>
<dt>User Name</dt>
<dd><input type="text" class="form-control"></dd>
<dt>Password</dt>
<dd><input type="password" class="form-
control"></dd>
<dt>Email</dt>
<dd><input type="email" class="form-control"></dd>
</dl>
<button class="btn btn-primary w-100">Register</button>
</form>
</div>
Command Description
----------------------------------------------------------------------------------
------
ng generate component name It generates a new
component with
code behind technique.
(or) .html
.css
ng g c name .ts
.spec.ts
It registers component in
AppModule.
Ex:
> ng generate component electronics --skip-tests --inline-
style --inline-template
Multiple Components:
1. Add Netflix folder in "app"
2. Generate Components
D:\my-angular-workspace\projects\shopping\src\app\netflix>ng
g c netflix-header --skip-tests
D:\my-angular-workspace\projects\shopping\src\app\netflix>ng
g c netflix-main --skip-tests
D:\my-angular-workspace\projects\shopping\src\app\netflix>ng
g c netflix-register --skip-tests
D:\my-angular-workspace\projects\shopping\src\app\netflix>ng
g c netflix-index --skip-tests
3. netflix-index.component.html
.css
#background {
background-image: url("/assets/netflixback.png");
height: 768px;
}
#box {
margin: -30px;
background-color: rgba(0,0,0,0.5);
height: 768px;
}
4. netflix-header.component.html
.css
.brand {
font-size: 30px;
color:red;
}
5. netflix-main.component.html
<div>
<h1>Unlimited movies, TV shows and more.
</h1>
<h2> Watch anywhere. Cancel anytime.</h2>
<div class="mt-4">
<app-netflix-register></app-netflix-register>
</div>
<div class="mt-4">
<app-netflix-register></app-netflix-register>
</div>
</div>
.css
div {
color:white;
text-align: center;
}
6. netflix-register.component.html
<div>
<p>Ready to watch? Enter your email to create or restart
your membership.</p>
<div class="input-group input-group-lg">
<input type="email" placeholder="Your email address"
class="form-control">
<button class="btn btn-danger">
Get Started <span class="bi bi-chevron-right"></span>
</button>
</div>
</div>
Data Binding in Angular
==================
- Data Binding is a technique that allows the data to bind with
UI.
- It is a process of accessing data from source and presenting
in the UI, identifying the changes in UI and updating back to
data source.
- JavaScript and jQuery depends on lot of DOM manipulations
and Events.
- Angular can handle data binding by using frameworks like
a) MVC
b) MVVM
- Framework can bind and update without using explicit
events.
What is MVC?
- MVC is Model View Controller
- Trygve introduced the concept of MVC in early 1970's.
- First formulated with a language called "Small Talk".
- Code separation and reusability concerns.
- MVC is known to various technologies
Java Spring
PHP CakePHP, Code Igniter
Python Django, Flask, Grock
Ruby Ruby on Rails
.NET ASP.NET MVC
JavaScript SPINE, Angular
Model
=====
- It represents the data we are working with.
- It comprises of data specific logic and queries.
- It is an abstraction of data in memory.
- It may contain data validations.
View
====
- It represents the User Interface.
- It describes the presentation.
- It is under the control of view engine, which is now removed
Angular 13.
- View Engine responsibility is to render the output.
- Angular upto 13 version used a view engine called "Ivy".
- Babel manages rendering from Angular 13.
SPARK
NAHML
Django
Razor
ASPX
Controller
========
- It defines application specific logic.
- It is the core MVC component.
- It handle overall application flow.
- It can fetch data from source and present in UI, identify
changes in UI and update back to Model.
Interpolation:
- It uses a data binding expression. "{{ }}"
- It will not bind to any HTML element, It is just used as literal.
- Literal will not be embedded into element.
- As literal it can't handle certain properies of HTML element.
Syntax:
product:any = {
Name: 'Samsung TV'
}
product:any = {
Stock: true
}
Property Binding
=============
- You can access any HTML element property using property
binding entity "[ ]" and bind the dynamic value.
Syntax:
product:any = {
Stock : true
}
Syntax:
width:number = 400;
height:number = 100;
img.src;
img.className
<table height="400">
table.style.height="100px";
Attribute Binding
============
- It allows to bind any dynamic value to element attribute.
- The attributes are defined by using "attr" prefix.
[attr.AttributeName] = "dynamicValue"
<table [attr.height]="tableHeight">
Ex:
databinding.component.ts
@Component({
selector: 'app-databinding',
templateUrl: './databinding.component.html',
styleUrls: ['./databinding.component.css']
})
export class DatabindingComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
product:any = {
Name: 'Samsung TV',
Price: 56000.55,
Stock: false
}
tableHeight:number = 100;
tableWidth:number = 500;
tableBorder:number = 1;
}
databinding.component.html
<div class="container-fluid">
<h2>Table</h2>
<table [border]="tableBorder" [width]="tableWidth"
[attr.height]="tableHeight">
<tr>
<td>{{product.Name}}</td>
</tr>
</table>
<h2>Product Details</h2>
<dl>
<dt>Name</dt>
<dd>{{product.Name}}</dd>
<dt>Price</dt>
<dd>{{product.Price}}</dd>
<dt>Stock</dt>
<dd><input type="checkbox" [checked]="product.Stock" >
Available</dd>
</dl>
</div>
Ex:
1. Go to "app.module.ts"
imports: [
FormsModule
]
2. data.component.ts
3. data.component.html
<div class="container-fluid">
<h2>Product Details</h2>
<dl>
<dt>Name</dt>
<dd>
<input type="text" [(ngModel)]="productName">
</dd>
<dt>Stock</dt>
<dd>
<input type="checkbox" [(ngModel)]="Stock" >
Available
</dd>
<dt>Shipped To</dt>
<dd>
<select [(ngModel)]="City">
<option>Hyd</option>
<option>Mumbai</option>
<option>Delhi</option>
</select>
</dd>
</dl>
Product Name : {{productName}} <br>
Stock : {{(Stock==true)?'Available':'Out of Stock'}} <br>
Shipped To : {{City}}
</div>
MVVM
[Model View - View Model]
- Model represents data.
- View represents UI.
- View Model represents the data logic at UI.
- It eliminates the interaction with controller in data binding.
- It is good for inline techniques.
- Extensibility and speration issues.
- Heavy on UI.
- NgModel is used for binding data and updating at view level.
- NgModel requires a model reference for every element.
Syntax:
<input
type="text" name="Price" ngModel #Price="ngModel">
Ex:
databinding.component.ts
// no changes requires
databinding.component.html
<div class="container-fluid">
<div class="row">
<div class="col-3">
<h2>Register Product</h2>
<dl>
<dt>Name</dt>
<dd><input type="text" name="Name" ngModel
#Name="ngModel" class="form-control"></dd>
<dt>Price</dt>
<dd><input type="text" name="Price" ngModel
#Price="ngModel" class="form-control"></dd>
<dt>Stock</dt>
<dd class="form-switch">
<input class="form-check-input" ngModel
#Stock="ngModel" name="Stock" type="checkbox"> Available
</dd>
<dt>Shipped To</dt>
<dd>
<select name="City" ngModel #City="ngModel"
class="form-select">
<option>Delhi</option>
<option>Hyd</option>
</select>
</dd>
</dl>
</div>
<div class="col-9">
<h2>Product Details</h2>
<dl>
<dt>Name</dt>
<dd>{{Name.value}}</dd>
<dt>Price</dt>
<dd>{{Price.value}}</dd>
<dt>Stock</dt>
<dd>{{(Stock.value==true)?"Available":"Out of
Stock"}}</dd>
<dt>Shipped To</dt>
<dd>{{City.value}}</dd>
</dl>
<h3>Name object Properties</h3>
Pristine : {{Name.pristine}} <br>
Dirty : {{Name.dirty}} <br>
Valid : {{Name.valid}} <br>
Invalid : {{Name.invalid}} <br>
Touched : {{Name.touched}} <br>
Untouched : {{Name.untouched}}
</div>
</div>
</div>
fetch() JavaScript
$.ajax() jQuery
$.getJSON() jQuery
HttpClient Angular
Syntax:
fetch('api_url')
.then(function(response){
return response.json();
})
.then(function(data){
// use data
})
Syntax: Arrow
fetch('api_url')
.then(response=>response.json())
.then(data=> { // use data } )
Ex:
databinding.component.ts
@Component({
selector: 'app-databinding',
templateUrl: './databinding.component.html',
styleUrls: ['./databinding.component.css']
})
product:any = {};
productId:number = 5;
constructor() { }
ngOnInit(): void {
fetch(`http://fakestoreapi.com/products/${this.productId}`)
.then(response=> response.json())
.then(data=> {
this.product = data;
})
}
databinding.component.html
<div class="container-fluid">
<h2>Product Details</h2>
<div class="mb-2 w-50">
<input type="range" [(ngModel)]="productId" min="1"
value="1" max="20" class="form-range">
</div>
<div class="card m-3 p-3 w-50">
<img [src]="product.image" height="200" class="card-img-
top">
<div class="card-header" style="height: 140px;">
<h3>{{product.title}}</h3>
<p>{{product.price}}</p>
</div>
<div class="card-body">
<p>{{product.description}}</p>
</div>
<div class="card-footer">
<span class="bi bi-star-fill text-success"></span>
{{product.rating.rate}}
<span class="text-light">[product.rating.count]</span>
</div>
</div>
</div>
Angular Directives
===============
- Directive is a function that can
a) return markup
b) extend markup
c) make markup more interactive
- All directives will not have the same behaviour.
- Directive can be used as
a) Element
b) Attribute
<app-login> Element
ngModel Attribute
a) Structrual Directives
b) Attribute Directives
c) Component Directives
Structural Directives:
- A structural directive can control DOM structure.
- It can
a) Add Elements
b) Remove Elements
c) Repeat Elements
- Angular Structural directives are
ngIf
ngSwitch
ngFor
NgIf
=====
- It is a structural directive used to add or remove any element
from DOM.
- It uses a boolean value "true or false".
Note:
- Structural directives are added to element by using "*"
<div *ngIf="" >
Syntax:
<dd *ngIf="false">
<img [src]="" width="" height="">
</dd>
Ex:
ifdemo.component.ts
@Component({
selector: 'app-ifdemo',
templateUrl: './ifdemo.component.html',
styleUrls: ['./ifdemo.component.css']
})
export class IfdemoComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
product:any = {
Name: 'Nike Casuals',
Price: 6000.44,
Preview: 'assets/shoe.jpg'
}
ifdemo.component.html
<div class="container-fluid">
<h2>Product Details</h2>
<dl>
<dt>Name</dt>
<dd>{{product.Name}}</dd>
<dt>Price</dt>
<dd>{{product.Price}}</dd>
<dt class="form-switch">
<input name="preview" ngModel #preview="ngModel"
class="form-check-input" type="checkbox">
{{(preview.value)?'Hide Preview':'Show Preview'}}
</dt>
<dd *ngIf="preview.value">
<img [src]="product.Preview" width="200" height="200">
</dd>
</dl>
</div>
NgIf with Alternative Code Blocks
=========================
- An alternative code block is used to display content when
condition evaluates to false.
- NgIf can use alternative block, which is reffered as "then"
block
- NgIf can use "then" block with "else" block to identify the
condition and return a suitable presentation.
Syntax:
<div *ngIf="booleanExpression; then thenBlock else
elseBlock">
</div>
<ng-template>
... your markup or content....
</ng-template>
<ng-template #name>
</ng-template>
Syntax:
Ex:
ifdemo.component.ts
isVisible:boolean = true;
ifdemo.component.html
<div class="container-fluid">
<div *ngIf="isVisible; then thenBlock; else elseBlock"></div>
<ng-template #thenBlock>
Template to display when condition true
</ng-template>
<ng-template #elseBlock>
Template to display when condition false
</ng-template>
</div>
Ex:
ifdemo.component.ts
@Component({
selector: 'app-ifdemo',
templateUrl: './ifdemo.component.html',
styleUrls: ['./ifdemo.component.css']
})
export class IfdemoComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
product:any = {
Name: 'Nike Causals',
Preview: 'assets/shoe.jpg',
Description: 'something about nike casuals'
}
btnText:string = 'Description';
togglePreview:boolean = true;
PreviewClick(){
this.togglePreview = (this.togglePreview==true)?false:true;
this.btnText =
(this.btnText=='Description')?'Preview':'Description';
}
}
ifdemo.component.html
<div class="container-fluid">
<h2>Product Details</h2>
<dl>
<dt>Name</dt>
<dd>{{product.Name}}</dd>
<dt><button (click)="PreviewClick()" class="btn btn-
primary">{{btnText}}</button></dt>
<dd>
<div *ngIf="togglePreview; then preview; else
description"></div>
<ng-template #preview>
<img [src]="product.Preview" width="200"
height="200">
</ng-template>
<ng-template #description>
<p>{{product.Description}}</p>
</ng-template>
</dd>
</dl>
</div>
Content Projection
-------------------------
- Content Projection is a technique where templates are
configured explicitly and rendered into component according to
state and situation.
Syntax:
thenBlock1 : TemplateRef<any>;
- A "TemplateRef<T>" can handle Markup, Styles, Dynamic
values.
Ex:
ifdemo.component.ts
@Component({
selector: 'app-ifdemo',
templateUrl: './ifdemo.component.html',
styleUrls: ['./ifdemo.component.css']
})
export class IfdemoComponent implements OnInit {
thenBlock:TemplateRef<any>|null = null;
isVisible:boolean = true;
@ViewChild('Block1', {static:true})
Block1:TemplateRef<any>|null = null;
@ViewChild('Block2', {static:true})
Block2:TemplateRef<any>|null = null;
constructor() { }
ngOnInit(): void {
this.thenBlock = this.Block1;
}
SwitchClick(){
this.thenBlock =
(this.thenBlock==this.Block1)?this.Block2:this.Block1;
}
}
ifdemo.component.html
<div class="container-fluid">
<button (click)="SwitchClick()">
Switch Then Block
</button>
<div *ngIf="isVisible; then thenBlock; else elseBlock"></div>
<ng-template #Block1>
Then Block1
</ng-template>
<ng-template #Block2>
Then Block2
</ng-template>
<ng-template #elseBlock>
else block
</ng-template>
</div>
• Ex: Content Projection
ifdemo.component.ts
@Component({
selector: 'app-ifdemo',
templateUrl: './ifdemo.component.html',
styleUrls: ['./ifdemo.component.css']
})
export class IfdemoComponent implements OnInit {
product:any = {};
GetData(id:number) {
fetch(`http://fakestoreapi.com/products/${id}`)
.then(response=>response.json())
.then(data => {
this.product = data;
})
}
count:number = 1;
ButtonText:string = 'Price | Rating';
ToggleTemplate:TemplateRef<any>|null = null;
constructor() { }
ngOnInit(): void {
this.GetData(this.count);
this.ToggleTemplate = this.DescriptionTemplate;
}
NextClick(){
this.count++;
this.GetData(this.count);
}
PreviousClick(){
this.count--;
this.GetData(this.count);
}
ToggleDetails(){
this.ToggleTemplate =
(this.ToggleTemplate==this.DescriptionTemplate)?this.RatingT
emplate: this.DescriptionTemplate;
this.ButtonText = (this.ButtonText=='Price |
Rating')?'Description':'Price | Rating';
}
ifdemo.component.html
<div class="container-fluid">
<div class="mt-3 btn-group">
<button (click)="PreviousClick()" class="btn btn-danger">
« </button>
<button (click)="NextClick()" class="btn btn-warning">
» </button>
</div>
<div class="card w-25 m-2 p-2">
<img [src]="product.image" height="200" class="card-img-
top">
<div class="card-header" style="height: 170px;">
<h5>{{product.title}}</h5>
</div>
</div>
<div class="details">
<button (click)="ToggleDetails()" class="btn btn-primary">
<span class="bi bi-eye-fill"></span>
{{ButtonText}}
</button>
<div *ngIf="true; then ToggleTemplate"></div>
<ng-template #DescriptionTemplate>
<h2>Product Description</h2>
<p>{{product.description}}</p>
</ng-template>
<ng-template #RatingTemplate>
<h2>Product Price | Rating</h2>
<dl>
<dt>Price</dt>
<dd>{{product.price}}</dd>
<dt>Rating</dt>
<dd>
<span class="bi bi-star-fill text-success"></span>
{{product.rating.rate}} [<span class="text-
dark">{{product.rating.count}}</span>]
</dd>
</dl>
</ng-template>
</div>
</div>
ifdemo.component.css
.details {
position: fixed;
right: 320px;
top: 100px;
width: 400px;
}
Syntax:
<parent-container [ngSwitch]="CaseString">
<child-container *ngSwitchCase=" 'case1' ">
</child-container>
<child-container *ngSwitchDefault>
</child-container>
</parent-container>
switchdemo.component.html
<div class="container-fluid">
<div [ngSwitch]="'case4'">
<div *ngSwitchCase="'case1'">
Container Case-1
</div>
<div *ngSwitchCase="'case2'">
Container Case-2
</div>
<div *ngSwitchCase="'case3'">
Container Case-3
</div>
<div *ngSwitchDefault>
Container Case Default
</div>
</div>
</div>
switchdemo.component.ts
@Component({
selector: 'app-switchdemo',
templateUrl: './switchdemo.component.html',
styleUrls: ['./switchdemo.component.css']
})
export class SwitchdemoComponent implements OnInit {
product:any = {};
GetData(productid:number) {
fetch(`http://fakestoreapi.com/products/${productid}`)
.then(response=> response.json())
.then(data=> {
this.product = data;
})
}
TemplateToDisplay:string = 'basic';
constructor() { }
ngOnInit(): void {
this.GetData(2);
}
ChangeTemplate(e:any){
this.TemplateToDisplay = e.target.name;
}
switchdemo.component.html
<div class="container-fluid">
<h2>Product Details</h2>
<div class="btn-toolbar bg-danger">
<div class="btn-group">
<button (click)="ChangeTemplate($event)"
name="basic" class="btn btn-danger">Basic Details</button>
<button (click)="ChangeTemplate($event)"
name="preview" class="btn btn-danger">Preview</button>
<button (click)="ChangeTemplate($event)"
name="rating" class="btn btn-danger">Price and
Rating</button>
<button (click)="ChangeTemplate($event)"
name="description" class="btn btn-
danger">Description</button>
</div>
</div>
<div class="mt-3" [ngSwitch]="TemplateToDisplay">
<div *ngSwitchCase="'basic'">
<h3>Product Title</h3>
<p>{{product.title}}</p>
</div>
<div *ngSwitchCase="'preview'">
<h3>Preview</h3>
<img [src]="product.image" width="200" height="200">
</div>
<div *ngSwitchCase="'rating'">
<h3>Price and Rating</h3>
<dl>
<dt>Price</dt>
<dd>{{product.price}}</dd>
<dt>Rating</dt>
<dd>
<span class="bi bi-star-fill text-success"></span>
{{product.rating.rate}} [{{product.rating.count}}]
</dd>
</dl>
</div>
<div *ngSwitchCase="'description'">
<h3>Description</h3>
<p>
{{product.description}}
</p>
</div>
</div>
</div>
https://api.nasa.gov/mars-
photos/api/v1/rovers/curiosity/photos?sol=1000 HYPERLINK
"https://api.nasa.gov/mars-
photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=DEM
O_KEY"& HYPERLINK "https://api.nasa.gov/mars-
photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=DEM
O_KEY"api_key=DEMO_KEY
Present
- Image Preview
- Rover Name
- Camera Name
- Date taken
NgFor
======
- It is a repeater, used to repeat any HTML element.
- It can create element dynamically and repeat according to
given iterator.
- It uses an iterator for repeating elements.
- Iterator is a software design pattern used to read elements
from a collection in sequential order.
- NgFor uses "for..of" iterator
JavaScript:
- It have to create element dynamically
- Set properties to element
- Append element to its parent.
Ex:
<head>
<script>
var categories = ['Electronics', 'Footwear', 'Fashion'];
function bodyload(){
for(var item of categories)
{
var li = document.createElement("li");
li.innerHTML = item;
document.querySelector("ol").appendChild(li);
</ol>
<select>
</select>
</body>
Angular:
- It uses "ngFor" to create element dynamically and repeat
according to iterator.
Syntax:
collection = [ 'A', 'B', 'C' ];
<ol>
<li *ngFor="let item of collection"> {{ item }} </li>
</ol>
<select>
<option *ngFor="let item of collection" [value]="item">
{{item}}
</option>
</select>
<tbody>
<tr *ngFor="let item of collection">
<td> {{item}} </td>
</tr>
</tbody>
Ex:
fordemo.component.ts
@Component({
selector: 'app-fordemo',
templateUrl: './fordemo.component.html',
styleUrls: ['./fordemo.component.css']
})
export class FordemoComponent implements OnInit {
categories:any[] = [];
GetCategories(){
fetch('http://fakestoreapi.com/products/categories
HYPERLINK "http://fakestoreapi.com/products/categories&"&
HYPERLINK
"http://fakestoreapi.com/products/categories&"#39;)
.then(response=> response.json())
.then(data=> {
data.unshift("all")
this.categories = data;
})
}
constructor() { }
ngOnInit(): void {
this.GetCategories();
}
fordemo.component.html
<div class="container-fluid">
<h2>NgFor Demo</h2>
<div class="row">
<div class="col">
<ol>
<li *ngFor="let item of categories">
{{item}}
</li>
</ol>
</div>
<div class="col">
<select class="form-select">
<option *ngFor="let item of categories">
{{item}}
</option>
</select>
</div>
<div class="col">
<div class="p-4" style="height: 80px; border:2px solid
black; overflow: auto;">
<ul class="list-unstyled">
<li *ngFor="let item of categories">
<input type="checkbox"> {{item}}
</li>
</ul>
</div>
</div>
<div class="col">
<table class="table table-hover table-dark">
<thead>
<tr>
<th>Categories</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of categories">
<td>{{item}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
Nested Iterations
==============
- NgFor allows nested approach, where you can define a
repeater within another repeater.
<head>
<script>
var data = [
{Category: "Electronics", Products: ["TV", "Mobile"]},
{Category: "Footwear", Products:["Nike Casuals", "Lee
Boot"]}
];
function bodyload(){
for(var item of data)
{
var li = document.createElement("li");
li.innerHTML = item.Category;
document.querySelector("ol").appendChild(li);
for(var product of item.Products)
{
var ul = document.createElement("ul");
var ulLi = document.createElement("li");
ulLi.innerHTML = product;
ul.appendChild(ulLi);
document.querySelector("ol").appendChild(ul);
}
}
}
</script>
</head>
<body onload="bodyload()">
<ol>
</ol>
</body>
Ex:
fordemo.component.ts
@Component({
selector: 'app-fordemo',
templateUrl: './fordemo.component.html',
styleUrls: ['./fordemo.component.css']
})
export class FordemoComponent implements OnInit {
data:any[] = [
{Category: "Electronics", Products: ["TV", "Mobile"]},
{Category: "Footwear", Products:["Nike Casuals", "Lee
Boot"]}
];
constructor() { }
ngOnInit(): void {
fordemo.component.html
<div class="container-fluid">
<h2>NgFor Nested Demo</h2>
<div class="row">
<div class="col">
<ol>
<li *ngFor="let item of data">
{{item.Category}}
<ul>
<li *ngFor="let product of item.Products">
{{product}}
</li>
</ul>
</li>
</ol>
</div>
<div class="col">
<select class="form-select">
<optgroup *ngFor="let item of data"
[label]="item.Category">
<option *ngFor="let product of item.Products">
{{product}}
</option>
</optgroup>
</select>
</div>
</div>
</div>
fordemo.component.ts
@Component({
selector: 'app-fordemo',
templateUrl: './fordemo.component.html',
styleUrls: ['./fordemo.component.css']
})
export class FordemoComponent implements OnInit {
MarsObject:any = {};
GetMarsPhotos(){
fetch('https://api.nasa.gov/mars-
photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=DEM
O_KEY’)
.then(response=> response.json())
.then(data=> {
this.MarsObject = data;
})
}
constructor() { }
ngOnInit(): void {
this.GetMarsPhotos();
}
}
fordemo.component.html
<div class="container-fluid">
<h2>Mars Photos</h2>
<table class="table table-hover">
<thead>
<tr>
<th>Photo Id</th>
<th>Camera Name</th>
<th>Image</th>
<th>Rover Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of MarsObject.photos">
<td>{{item.id}}</td>
<td>{{item.camera.full_name}}</td>
<td>
<img [src]="item.img_src" width="100"
height="100">
</td>
<td>
{{item.rover.name}}
</td>
</tr>
</tbody>
</table>
</div>
fordemo.component.html
<div class="container-fluid">
<h2>Mars Photos</h2>
<div class="d-flex flex-wrap">
<div *ngFor="let item of MarsObject.photos" class="card
m-3 p-2" style="width: 200px;">
<img [src]="item.img_src" height="200" class="card-
img-top">
<div class="card-header">
<h3>{{item.id}}</h3>
</div>
<div class="card-body">
<dl>
<dt>Camera Name</dt>
<dd>{{item.camera.full_name}}</dd>
<dt>Rover Name</dt>
<dd>{{item.rover.name}}</dd>
</dl>
</div>
</div>
</div>
</div>
ngFor properties
- index
- first
- last
- even
- odd
- trackBy
NgFor Properties
==============
Syntax:
<li *ngFor="let item of collection; let i=index; let e=even">
Ex:
indexdemo.component.ts
@Component({
selector: 'app-indexdemo',
templateUrl: './indexdemo.component.html',
styleUrls: ['./indexdemo.component.css']
})
export class IndexdemoComponent implements OnInit {
products:any[] = [];
productName:string = '';
productPrice:number = 0;
product:any = {};
constructor() { }
ngOnInit(): void {
}
RegisterClick(){
this.product = {
Name: this.productName,
Price: this.productPrice
}
this.products.push(this.product);
alert('Product Registered..');
this.productName = '';
this.productPrice = 0;
}
DeleteClick(index:number){
let flag = confirm('Are you sure, want to Delete?');
if(flag==true) {
this.products.splice(index,1);
}
}
indexdemo.component.html
<div class="container-fluid">
<div class="row">
<div class="col-3">
<h2>Register Product</h2>
<dl>
<dt>Name</dt>
<dd><input type="text" [(ngModel)]="productName"
class="form-control"></dd>
<dt>Price</dt>
<dd><input type="text" [(ngModel)]="productPrice"
class="form-control"></dd>
</dl>
<button (click)="RegisterClick()" class="btn btn-primary
w-100">Register</button>
</div>
<div class="col-9">
<h2>Product Details</h2>
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr [class.even-style]="even" [class.odd-style]="odd"
*ngFor="let item of products; let i=index; let even=even; let
odd=odd">
<td>{{item.Name}}</td>
<td>{{item.Price}}</td>
<td>
<button (click)="DeleteClick(i)" class="btn btn-
danger">
<span class="bi bi-trash-fill"></span>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
indexdemo.component.css
.even-style
{
background-color: rgb(209, 252, 209);
}
.odd-style {
background-color: rgb(250, 194, 194);
}
Ex:
trackdemo.component.ts
@Component({
selector: 'app-trackdemo',
templateUrl: './trackdemo.component.html',
styleUrls: ['./trackdemo.component.css']
})
export class TrackdemoComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
products:any[] = [
{Name: 'TV', Price: 46000.55},
{Name: 'Mobile', Price:23000.44},
{Name: 'Nike Casuals', Price: 6300.33}
];
AddNewProduct(){
this.products = [
{Name: 'TV', Price: 46000.55},
{Name: 'Mobile', Price:23000.44},
{Name: 'Nike Casuals', Price: 6300.33},
{Name: 'Watch', Price: 6700.55}
];
alert('Add Clicked');
}
TrackChanges(index:number) {
return index;
}
trackdemo.component.html
<div class="container-fluid">
<button (click)="AddNewProduct()" class="btn btn-
primary">Add New</button>
<div>
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of products;
trackBy:TrackChanges">
<td>{{item.Name}}</td>
<td>{{item.Price}}</td>
</tr>
</tbody>
</table>
</div>
</div>
component.ts
products:any[] = [
{Name: 'Nike Casuals', Photo: 'assets/shoe.jpg', Likes:0,
Dislikes:0},
{Name: 'Lee Boot', Photo: 'assets/shoe1.jpg', Likes:0,
Dislikes:0}
]
constructor() { }
ngOnInit(): void {
}
LikesClick(item:any){
item.Likes++;
}
DislikesClick(item:any) {
item.Dislikes++;
}
component.html
<div class="container-fluid">
<div class="d-flex flex-wrap m-3">
<div class="card m-2 p-2" *ngFor="let item of products"
style="width: 400px;">
<img [src]="item.Photo" height="200px" class="card-img-
top">
<div class="card-header">
<h3>{{item.Name}}</h3>
</div>
<div class="card-footer btn-group">
<button (click)="LikesClick(item)" class="btn btn-
success">
<span class="bi bi-hand-thumbs-up-fill"></span>
[{{item.Likes}}] Like(s)
</button>
<button (click)="DislikesClick(item)" class="btn btn-
danger">
<span class="bi bi-hand-thumbs-down-fill"></span>
[{{item.Dislikes}}] Dislike(s)
</button>
</div>
</div>
</div>
</div>
Summary:
- ngIf
- ngIF content projection
- ngSwitch
- ngFor
Attribute Directives
===============
- Attributes directive are used to extend HTML.
- They can make HTML more interactive and responsive.
- They will convert a static HTML element into dynamic
element.
- Angular attribute directives are:
a) NgClass
b) NgStyle
c) NgModel
NgClass:
=======
- It is used to define a CSS class dynamically.
- You can change the appearence of element dynamically.
Syntax:
<div [ngClass]=" 'className' ">
<div [ngClass]="[ 'class1', 'class2' ]">
<div [ngClass]="{ 'class1:true', 'class2:false' }">
Ex:classdemo.component.css
.text-style{
color: red;
text-align: center;
}
.border-style{
border: 2px solid red;
padding: 5px;
}
.back-style{
background-color: yellow;
}
Classdemo.component.html
<div class="container-fluid mt-2">
<h2 [ngClass]="'text-style'">Class Binding</h2>
<h2 [ngClass]="['text-style','border-style','back-
style']">Class Binding</h2>
<h3 [ngClass]="{'text-style':true,'border-
style':false,'back-style':true}">Class Binding</h3>
</div>
Ex:
classdemo.component.css
.dark-theme {
background-color: black;
color:white;
padding: 10px;
}
.invalid-style {
border:2px solid red;
box-shadow: 2px 2px 2px red;
}
.valid-style {
border:2px solid green;
box-shadow: 2px 2px 2px green;
}
classdemo.component.html
<div class="container-fluid">
<div class="d-flex justify-content-center align-items-center"
style="height: 400px;">
<form [ngClass]="{'dark-theme':Theme.value}">
<div class="form-switch">
<input type="checkbox" name="Theme" ngModel
#Theme="ngModel" class="form-check-input"> Dark Theme
</div>
<h2>Register User</h2>
<dl>
<dt>User Name</dt>
<dd><input type="text" [ngClass]="{'invalid-
style':UserName.invalid, 'valid-style':UserName.valid}"
name="UserName" ngModel #UserName="ngModel" required
class="form-control"></dd>
<dt>Password</dt>
<dd><input type="password" [ngClass]="{'invalid-
style':Password.invalid, 'valid-style':Password.valid}"
name="Password" ngModel #Password="ngModel" required
minlength="4" class="form-control"></dd>
</dl>
<button class="btn btn-primary w-
100">Register</button>
</form>
</div>
</div>
NgStyle
======
- It is used to configure inline styles.
- Inline styles are native to element.
- NgStyle uses a style object that can change dynamically.
- You can configure styles for any element dynamically
according to state and situation.
- It doesn't require ".css" or external class, which will reduce
the number of request for component and improves the render
time.
- But have reusablity concerns.
Syntax:
styleObject = {
'styleAttribute' : value
}
Ex:
classdemo.component.ts
@Component({
selector: 'app-classdemo',
templateUrl: './classdemo.component.html',
styleUrls: ['./classdemo.component.css']
})
export class ClassdemoComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
styleObject = {
'position': 'fixed',
'top': '',
'left': ''
}
MouseMove(event:any) {
console.log(`X=${event.clientX}\nY=${event.clientY}`);
this.styleObject = {
'position' : 'fixed',
'top': event.clientY + 'px',
'left': event.clientX + 'px'
}
}
}
classdemo.component.html
<div (mousemove)="MouseMove($event)">
<div class="container-fluid" style="height: 1000px;">
</div>
<img [ngStyle]="styleObject" src="assets/flag.gif"
width="50" height="50">
</div>
Note: You can configure a method that can return style object
and use the method for HTML element.
Syntax:
GetStyles() {
return {
'attribute': value
}
}
NgModel
=======
- It is an attribute directive that allocates memory for element
to store its value.
- NgModel is 'Single-Source-Of-Truth'.
- It can keep information about value and its changes.
a) Previous Value
b) Current Value
- It can bind value to property, identify changes in value and
update to source.
Syntax: MVC
Syntax: MVVM
Syntax:
<button onclick="ButtonClick(this, event)">
Syntax:
<button (click)="ButtonClick($event)">
Keyboard Events:
- keyup
- keydown
- keypress
Ex: KeyEvents
eventdemo.component.ts
@Component({
selector: 'app-eventdemo',
templateUrl: './eventdemo.component.html',
styleUrls: ['./eventdemo.component.css']
})
export class EventdemoComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
users:any[] = [
{UserName: 'john'},
{UserName: 'john12'},
{UserName: 'john_nit'},
{UserName: 'david'}
];
statusMessage:string = '';
isNameAvailable:boolean = true;
VerifyUser(e:any){
for(var user of this.users) {
if(user.UserName==e.target.value){
this.statusMessage = 'User Name Taken - Try
Another';
this.isNameAvailable = false;
break;
} else {
this.statusMessage = 'User Name Available';
this.isNameAvailable = true;
}
}
}
showCapsError:boolean = false;
VerifyPassword(e:any){
if(e.keyCode>=65 && e.keyCode<=90) {
this.showCapsError = true;
} else {
this.showCapsError = false;
}
}
}
eventdemo.component.html
<div class="container-fluid">
<h2>Register User</h2>
<dl>
<dt>User Name</dt>
<dd><input type="text"
(keyup)="VerifyUser($event)"></dd>
<dd [ngClass]="{'text-
success':isNameAvailable}">{{statusMessage}}</dd>
<dt>Password</dt>
<dd><input type="password"
(keypress)="VerifyPassword($event)" ></dd>
<dd class="text-warning" *ngIf="showCapsError">
<span class="bi bi-exclamation-triangle-fill"></span>
Caps ON
</dd>
</dl>
</div>
<form (submit)="SubmitClick()">
<form (ngSubmit)="SubmitClick()">
Syntax:
<form #refName="ngForm">
<form #frmRegister="ngForm">
SubmitClick(formObject:any)
{
alert(JSON.stringfy(formObject));
}
Angular Event Binding
What is Event?
• Event is a message sent by sender to its subscriber in order to
notify the change.
• Event follows a software design pattern called “Observer”.
• Observer is a communication pattern under “Behavioural
Patterns”.
public method(event) {
event.eventProperties;
event.target.objectProperties
}
Key Event Binding
• It defines the actions to perform when user is keying in the
characters.
• The key events are
Event Description
keyup Specifies actions to perform when key is
released
Keydown Specifies actions to perform when user hold
down a key
keypress Specifies actions to perform when user finish a
key.
[finish typing a key and use any another key]
@Component({
selector: 'app-keydemo',
templateUrl: './keydemo.component.html',
styleUrls: ['./keydemo.component.css']
})
export class KeydemoComponent{
users = [
{UserName: 'john'},
{UserName: 'john123'},
{UserName: 'david'},
{UserName: 'david_nit'}
];
username;
password;
regExp = /(?=.*[A-Z])\w{4,10}/;
message = '';
validStyle = false;
invalidStyle = false;
showWarning = false;
passwordMessage = '';
VerifyUser(){
for(var user of this.users){
if(user.UserName == this.username) {
this.message = 'User Name Taken - Try Another';
this.invalidStyle = true;
this.validStyle = false;
break;
} else {
this.message = 'User Name Available';
this.invalidStyle = false;
this.validStyle = true;
}
}
}
VerifyCaps(e) {
if(e.keyCode>=65 && e.keyCode<=90) {
this.showWarning = true;
} else {
this.showWarning = false;
}
}
VerifyPasswordStrength(){
if(this.password.match(this.regExp)){
this.passwordMessage = 'Strong Password';
} else {
if(this.password.length<4) {
this.passwordMessage = 'Poor Password';
} else {
this.passwordMessage = 'Weak Password';
}
}
}
}
Keydemo.component.html
<div>
<div class="form-register">
<h2>Register User</h2>
<div class="form-group">
<label>User Name</label>
<div>
<input [ngClass]="{'valid-effect': validStyle, 'invalid-effect':
invalidStyle}" (keyup)="VerifyUser()" [(ngModel)]="username"
type="text" class="form-control">
<span [ngClass]="{'text-danger':invalidStyle, 'text-success':
validStyle}">{{message}}</span>
</div>
</div>
<div class="form-group">
<label>Password</label>
<div>
<input [(ngModel)]="password"
(keyup)="VerifyPasswordStrength()" (keypress)="VerifyCaps($event)"
type="password" class="form-control">
<div>
<span *ngIf="showWarning" class="text-warning"> <span
class="fa fa-exclamation-triangle"></span> Caps is ON </span>
</div>
<div>
<span> {{passwordMessage}} </span>
</div>
</div>
</div>
</div>
</div>
Keydemo.component.css
.form-register {
width: 300px;
border:2px solid darkcyan;
padding: 20px;
margin:auto;
margin-top: 20px;
border-radius: 10px;
}
.valid-effect {
border:2px solid green;
box-shadow: 2px 3px 4px green;
}
.invalid-effect {
border:2px solid red;
box-shadow: 2px 3px 4px red;
}
@Component({
selector: 'app-mousedemo',
templateUrl: './mousedemo.component.html',
styleUrls: ['./mousedemo.component.css']
})
export class MousedemoComponent {
styleObj = {
'color': ''
};
zoomObject = {
'height': '',
'width': ''
};
offerImage = 'assets/giftbox.png';
SetColor(e){
this.styleObj = {
'color': e.target.id
};
}
startMarquee(e){
e.target.start();
}
stopMarquee(e){
e.target.stop();
}
zoomIN(){
this.zoomObject = {
'height': '400px',
'width': '400px'
};
}
zoomOut(){
this.zoomObject = {
'height': '100px',
'width': '100px'
};
}
showOffer(){
this.offerImage = 'assets/offerbox.png';
}
hideOffer(){
this.offerImage = 'assets/giftbox.png';
}
}
Mousedemo.component.html
<div>
<h2>Color Picker</h2>
<div class="row" (mouseover)="SetColor($event)" style="width:
500px; margin:auto">
<div class="col-4 bg-danger text-white" id="red">
Red
</div>
<div class="col-4 bg-success text-white" id="green">
Green
</div>
<div class="col-4 text-white" id="blue" style="background-color:
blue;">
Blue
</div>
</div>
<h2 align="center" [ngStyle]="styleObj" >Sample Text</h2>
<h2>Mouse over and out</h2>
<marquee (mouseover)="stopMarquee($event)"
(mouseout)="startMarquee($event)" scrollamount="10"
bgcolor="lightgreen">
<img src="assets/shoe.jpg" width="100" height="100">
<img src="assets/speaker.jpg" width="100" height="100">
<img src="assets/shirt.jpg" width="100" height="100">
<img src="assets/jeans.jpg" width="100" height="100">
</marquee>
<h2>Mouse Down and Up</h2>
<div style="width: 400px;">
<img [ngStyle]="zoomObject" (mousedown)="zoomIN()"
(mouseup)="zoomOut()" style="margin: auto;" src="assets/shoe.jpg"
width="100" height="100">
</div>
<h2>Mouse Down and Up</h2>
<div>
<img (mousedown)="showOffer()" (mouseup)="hideOffer()"
[src]="offerImage">
</div>
</div>
Mousedemo.component.css
img {
opacity: 0.8;
margin-left: 30px;
}
Other JavaScript Events used by Angular
Event Description
Blur Actions to perform when element loses the focus.
focus Actions to perform when element gets focus.
change Actions to perform when value is changed.
Cut
Copy
Paste
Select
Selectstart
Submit
Click
Dblclick
contextmenu
Ex:
Evendemo.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-eventdemo',
templateUrl: './eventdemo.component.html',
styleUrls: ['./eventdemo.component.css']
})
export class EventdemoComponent{
msg = '';
username;
products =
['assets/shoe.jpg','assets/shirt.jpg','assets/speaker.jpg','assets/earpo
ds.jpg'];
imageSource = 'assets/shoe.jpg';
sliderValue = 0;
onFocus(){
this.msg = 'Name in Block Letters';
}
onBlur(){
this.msg = '';
this.username = this.username.toUpperCase();
}
ChangeProduct(){
this.imageSource = this.products[this.sliderValue];
}
}
Evendemo.component.html
<div>
<h2>User Name</h2>
<div>
<input (focus)="onFocus()" (blur)="onBlur()"
[(ngModel)]="username" placeholder="Name in Block Letters"
type="text" class="form-control">
<span>{{msg}}</span>
</div>
<h2>Change</h2>
<div>
<label>Products</label>
<input [(ngModel)]="sliderValue" (change)="ChangeProduct()"
min="0" value="0" max="3" type="range">
</div>
<div>
<img [src]="imageSource" width="200" height="200">
</div>
</div>
Fakestore Shopping Cart
http://fakestoreapi.com/
- API Requests
GET http://fakestoreapi.com/products
[returns all products data - 20]
GET http://fakestoreapi.com/products/1
[returns specific product]
GET http://fakestoreapi.com/products/categories
[returns all categories - 4]
GET http://fakestoreapi.com/products/category/jewel
ery
[returns all products belong to specific category]
(change) : It is an event that triggers the action when
value changed.
textbox, dropdown, range, number etc..
shoppingcart.component.ts
@Component({
selector: 'app-shoppingcart',
templateUrl: './shoppingcart.component.html',
styleUrls: ['./shoppingcart.component.css']
})
export class ShoppingcartComponent implements OnInit {
categories:string[] = [];
GetCategories(){
fetch('http://fakestoreapi.com/products/categories
HYPERLINK "http://fakestoreapi.com/products/categories&"&
HYPERLINK
"http://fakestoreapi.com/products/categories&"#39;)
.then(response=> response.json())
.then(data=> {
data.unshift("all");
this.categories = data;
})
}
products:any[] = [];
GetProducts(){
fetch('http://fakestoreapi.com/products HYPERLINK
"http://fakestoreapi.com/products&"& HYPERLINK
"http://fakestoreapi.com/products&"#39;)
.then(response=> response.json())
.then(data=> {
this.products = data;
})
}
constructor() { }
ngOnInit(): void {
this.GetCategories();
this.GetProducts();
}
CategoryChanged(e:any){
if(e.target.value=='all') {
this.GetProducts();
} else {
fetch(`http://fakestoreapi.com/products/category/${e.target
.value}`)
.then(response=> response.json())
.then(data=> {
this.products = data;
})
}
}
CartItems:any[] = [];
AddToCartClick(product:any){
this.CartItems.push(product);
alert(`${product.title} \nAdded to Cart`);
this.GetCartItemsCount();
}
count:number = 0;
GetCartItemsCount(){
this.count = this.CartItems.length;
}
toggleCart:boolean = false;
Toggle(){
this.toggleCart = (this.toggleCart==false)?true:false;
}
}
shoppingcart.component.html
<div class="container-fluid">
<header class="p-2 bg-danger text-white text-center">
<h1> <span class="bi bi-cart3"></span> Fakestore -
Online Shopping</h1>
</header>
<section class="row">
<nav class="col-3">
<div class="mt-3">
<label class="form-label">Select a Category</label>
<div>
<select (change)="CategoryChanged($event)"
class="form-select">
<option [value]="category" *ngFor="let category of
categories">
{{category|titlecase}}
</option>
</select>
</div>
</div>
<div class="mt-2" *ngIf="toggleCart">
<label>Your Cart</label>
<table class="table table-hover">
<thead>
<tr>
<th>Title</th>
<th>Price</th>
<th>Preview</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of CartItems">
<td>{{item.title}}</td>
<td>{{item.price}}</td>
<td><img [src]="item.image" width="50"
height="50"></td>
</tr>
</tbody>
</table>
</div>
</nav>
<main class="col-7">
<div class="d-flex flex-wrap m-3 overflow-auto"
style="height: 500px;">
<div *ngFor="let product of products" class="card m-2
p-2" style="width: 200px;">
<img [src]="product.image" height="150"
class="card-img-top">
<div class="card-header" style="height: 160px;">
<p><b>{{product.title}}</b></p>
</div>
<div class="card-body">
<dl>
<dt>Price</dt>
<dd>{{product.price}}</dd>
<dt>Rating</dt>
<dd><span class="bi bi-star-fill text-
success"></span> {{product.rating.rate}}
[{{product.rating.count}}]</dd>
</dl>
</div>
<div class="card-footer">
<button (click)="AddToCartClick(product)"
class="btn btn-danger w-100">
<span class="bi bi-cart4"></span>
Add to Cart
</button>
</div>
</div>
</div>
</main>
<article class="col-2">
<div class="mt-3">
<button (click)="Toggle()" class="btn btn-danger w-
100"> <span class="bi bi-cart"></span> [{{count}}] Your Cart
Items</button>
</div>
</article>
</section>
</div>
Custom Events
FAQ: Why we need custom events?
Ans: In Angular we can create custom components.
A component is used in another component for handling
specific functionality.
In this case a component have its own events to
perform.
Syntax:
@Input() Property:DataType = Value;
Ex:
1. Add 2 components
> ng g c parent
> ng g c child
2. child.component.ts
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
ngOnInit(): void {
}
}
3. child.component.html
4. parent.component.ts
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
messageToChild:string|null =null;
objectToChild:any = {};
constructor() { }
ngOnInit(): void {
}
SendClick(){
this.messageToChild = 'Hello ! from parent';
this.objectToChild = {
'Name': 'TV',
'Price': 45500.33
}
}
}
5. parent.component.html
Syntax:
CustomEvent:EventEmitter<any> = new
EventEmitter<any>();
Syntax:
@Output() CustomEvent:EventEmitter<any> = ....
Syntax:
onSendClick() {
this.CustomEvent.emit(value | object);
}
<app-child (CustomEvent)="Method($event)">
</app-child>
Method(e:any)
{
e.value|object_property
}
Ex:
1. child.component.ts
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
@Input() message:string|null = 'waiting for message from
parent..';
@Input() obj:any = {};
messageToParent = 'Hello ! from Child';
@Output() ChildComponentClick:EventEmitter<string> =
new EventEmitter<string>();
@Output()
ChildComponentSendObjectClick:EventEmitter<any> = new
EventEmitter<any>();
ngOnInit(): void {
}
SendClick(){
this.ChildComponentClick.emit(this.messageToParent);
this.ChildComponentSendObjectClick.emit(this.product);
}
2. child.component.html
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
messageToChild:string|null =null;
objectToChild:any = {};
message:string|null = null;
constructor() { }
ngOnInit(): void {
}
SendClick(){
this.messageToChild = 'Hello ! from parent';
this.objectToChild = {
'Name': 'TV',
'Price': 45500.33
}
}
SendToParent(e:any) {
this.message = e;
}
Name:string = '';
Price:number = 0;
SendObject(e:any) {
this.Name = e.Name;
this.Price = e.Price;
}
}
4. parent.component.html
2. filter.component.ts
@Component({
selector: 'app-filter',
templateUrl: './filter.component.html',
styleUrls: ['./filter.component.css']
})
export class FilterComponent implements OnInit {
@Input() AllCount:number = 0;
@Input() ElectronicsCount:number = 0;
@Input() JeweleryCount:number = 0;
@Input() MensClothingCount:number = 0;
@Input() WomensClothingCount:number = 0;
constructor() { }
ngOnInit(): void {
}
FilterButtonClick(e:any){
this.FilterChanged.emit(e.target.name);
}
3. filter.component.html
4. products.component.ts
@Component({
selector: 'app-products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.css']
})
export class ProductsComponent implements OnInit {
products:any[] = [];
allCount:number = 0;
electronicsCount:number = 0;
jeweleryCount:number = 0;
mensCount:number = 0;
womensCount:number = 0;
GetProducts(){
fetch('http://fakestoreapi.com/products HYPERLINK
"http://fakestoreapi.com/products&"& HYPERLINK
"http://fakestoreapi.com/products&"#39;)
.then(response=> response.json())
.then(data=>{
this.products = data;
this.allCount = data.length;
this.electronicsCount = data.filter((product:any)=>
product.category=='electronics').length;
this.jeweleryCount = data.filter((product:any)=>
product.category=='jewelery').length;
this.mensCount = data.filter((product:any)=>
product.category==`men's clothing`).length;
this.womensCount =
data.filter((product:any)=>product.category==`women's
clothing`).length;
})
}
constructor() { }
ngOnInit(): void {
this.GetProducts();
}
categoryName:string = 'all';
GetCategoryName(e:any){
this.categoryName = e;
if(this.categoryName=='all') {
this.GetProducts();
} else {
fetch(`http://fakestoreapi.com/products/category/${this.cat
egoryName}`)
.then(response=>response.json())
.then(data=>{
this.products = data;
})
}
}
5. products.component.html
<div class="container-fluid">
<header class="bg-danger text-white text-center p-2 mb-2">
<h2>Fake Store - Online Shopping</h2>
</header>
<section class="row">
<nav class="col-3">
<app-filter
(FilterChanged)="GetCategoryName($event)"
[AllCount]="allCount" [ElectronicsCount]="electronicsCount"
[JeweleryCount]="jeweleryCount"
[MensClothingCount]="mensCount"
[WomensClothingCount]="womensCount" ></app-filter>
</nav>
<main class="col-9">
<div class="d-flex flex-wrap overflow-auto"
style="height: 500px;">
<div *ngFor="let item of products" class="card m-2 p-
2" style="width: 200px;">
<img [src]="item.image" height="200" class="card-
img-top">
<div class="card-header" style="height: 170px;">
<p>{{item.title}}</p>
</div>
<div class="card-footer">
<p>{{item.price}}</p>
</div>
</div>
</div>
</main>
</section>
</div>
Component Life Cycle
1. ngOnChanges()
- This is the first life cycle hook method for component.
- It declares the reference.
- Assigns or initializes value into references.
- Binding the values to element properties or attributes.
- Identify the changes in value and update back to source.
PreviousValue = undefined
CurrentValue = John
- ngOnChanges manages
a) Property Binding
b) Event Binding
2. ngOnInit()
- It initializes the memory for component, which is required
to store component data and use for the child component.
- Constructor allocates memory for component, but it is not
accessible to
child component.
- ngOnInit will initialize memory which is used for child
component to transport data.
3. ngDoCheck()
- Some values need explicit binding with properties.
- Some values need explicit events to identify changes.
- Changes in parent and update to child by using "@Input()"
- Values of child are emitted to parent by using "@Output()"
and custom event.
- It any value is not updated implicitly we have to configure
explicitly.
- It is managed by ngDoCheck.
- It manages transporting of data between parent and child.
ngOnChanges()
ngOnInit()
ngDoCheck()
ngAfterContentInit():
================
- The output is generated into View.
- The results are binded to UI elements.
- It renders the initial output.
- Values stored in reference are rendered into View [UI].
ngAfterContentChecked():
====================
- In this phase the external templates are rendered into UI.
- It will identify the templates by type "TemplateRef<T>"
- It will also identifies the dynamic templates in UI.
<ng-template>
- The templates are projected by @ViewChild() directive.
- Content Projection is managed in this phase.
ngAfterViewInit():
=============
- It initializes the memory for View [UI]
- This memory is used for transporting data across
components.
- It is used in MVVM approach.
ngAfterViewChecked():
==================
- In this phase the final rendering and painting is processed.
- Rendering the preparing the final output.
- Painting is generating the output and displaying in browser.
- After ngOnChanges and ngAfterContentChecked the final
output is generated in this phase.
ngOnDestroy():
============
- The memory allocated for component will be cleaned.
- It unsubscribes to the memory.
- It disconnects with data reference.
- It unsubscribes to the methods.
Change Detection
===============
1. Add following components
> ng g c parent
> ng g c child
2. child.component.ts
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges {
ngOnInit(): void {
}
3. child.component.html
4. parent.component.ts
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
UserName:any = 'David';
}
5. parent.component.html
Angular Material
Angular Components
How to Explore Components?
• Visit https://material.angular.io/components
• Select any component
• Go to “API” tab to know about the properties, methods and
modules required for component
• Know your component module name
• Know the dependencies for required module
• Know the selector for component
• Know the properties and methods for component
Syntax:
<mat-form-field appearance=”legacy | standard | fill |
outline”>
</mat-form-field>
@NgModule({
imports: [
BrowserModule,
FormsModule,
BrowserAnimationsModule,
MatFormFieldModule,
MatInputModule
],
})
• Go to your “component.html”
<div class="container">
<h2>Material Demo</h2>
<mat-form-field appearance="legacy" class="block-style" >
<mat-label>User Name</mat-label>
<input [(ngModel)]="UserName" type="text" matInput
placeholder="Enter User Name">
<mat-hint>Name in Block Letters</mat-hint>
<mat-error>Name Required</mat-error>
</mat-form-field>
<h3>Hello ! {{UserName}} </h3>
</div>
• Component.css
.block-style {
width: 100%;
}
• Component.ts
UserName = ‘ ‘;
Material Datepicker
• Modules
• MatDatepickerModule
• MatNativeDateModule
• Selectors
• mat-datepicker-toggle
• mat-datepicker
Ex:
• Import the following modules in “app.module.ts”
import { MatNativeDateModule } from
'@angular/material/core';
import { MatFormFieldModule } from
'@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatDatepickerModule } from
'@angular/material/datepicker';
imports: [
BrowserModule,
FormsModule,
BrowserAnimationsModule,
MatFormFieldModule,
MatInputModule,
MatDatepickerModule,
MatNativeDateModule
],
Component.html
<mat-form-field class="block-style mt-3">
<mat-label>Departure Date</mat-label>
<input type="text" matInput [matDatepicker]="picker" >
<mat-datepicker-toggle matSuffix [for]="picker" ></mat-
datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
Material Icons
Ex:
App.module.ts
import { MatIconModule } from '@angular/material/icon';
imports: [
BrowserModule,
FormsModule,
BrowserAnimationsModule,
MatFormFieldModule,
MatInputModule,
MatDatepickerModule,
MatNativeDateModule,
MatIconModule
],
<button>
<mat-icon>home</mat-icon>
Home
</button>
Angular CDK
(Component Dev Kit)
• It defines set of behaviour primitives for build UI component.
• It provides UX [User Experience]
Ex:
App.module.ts
import { ScrollingModule } from '@angular/cdk/scrolling';
[
ScrollingModule
]
Component.ts
products = [
{Name: 'JBL Speaker', Photo: 'assets/speaker.jpg'},
{Name: 'Earpods', Photo: 'assets/earpods.jpg'},
…. Add records
]
Component.html
<div class="container">
<h2>Lazy Loading - Virtual Scrolling</h2>
<cdk-virtual-scroll-viewport itemSize="100" class="view-port" >
<div class="card" *cdkVirtualFor="let product of products">
<img [src]="product.Photo" height="50" class="card-img-top">
<div class="card-body">
<h2>{{product.Name}}</h2>
</div>
</div>
</cdk-virtual-scroll-viewport>
</div>
Angular Material UI Components
mat-form-field
matinput
imports: [
MatDatepickerModule
]
<div class="container-fluid">
<h2>Date Picker</h2>
<mat-form-field appearence="legacy" >
<mat-label>Departure</mat-label>
<input matInput [matDatepicker]="picker" type="text">
<mat-datepicker-toggle matSuffix [for]="picker" ></mat-
datepicker-toggle>
<mat-datepicker #picker ></mat-datepicker>
</mat-form-field>
</div>
Material CDK
==========
- It provides behaviour for components.
- It is Component Development Kit
Angular Animations
---------------------------
- You can apply CSS transitions and transforms dynamically
to angular components.
- CSS Transforms
2D
3D
translate()
rotate()
scale()
skew()
matrix()
- CSS Transition
transition-duration
transition-delay
transition-property
transition-timing-function
@keyframes name
{
from { }
to { }
}
p{
animation-name: keyframeName
}
@Component(
{
selector: 'app-login',
templateUrl: 'htmlPage',
stylesUrl: [ 'stylesheet' ],
animations: [ ]
}
)
state('initial=>final') state('void=>*')
state('final=>initial') state('*=>void')
Syntax:
animations: [
trigger('name',
state('initial', styles({ })),
state('final', styles({ })),
transition('initial=>final', animate(4000)),
transition('final=>initial', animate(5000))
)
]
<h2 [@triggerName]='initial'>
Ex:
1. Add a new component
> ng g c animationdemo --skip-tests
2. animationdemo.component.ts
@Component({
selector: 'app-animationsdemo',
templateUrl: './animationsdemo.component.html',
styleUrls: ['./animationsdemo.component.css'],
animations: [
trigger('zoom', [
state('initial', style(
{
'width': '100px',
'height': '100px',
'transform': 'rotate(0deg)'
}
)),
state('final', style({
'width': '300px',
'height': '300px',
'transform': 'rotate(360deg)'
})),
transition('initial=>final', animate(4000)),
transition('final=>initial', animate(3000))
])
]
})
export class AnimationsdemoComponent implements OnInit {
animationState:any = 'initial';
buttonText:string = 'In';
constructor() { }
ngOnInit(): void {
}
ZoomClick(){
this.animationState =
(this.animationState=='initial')?'final':'initial';
this.buttonText = (this.buttonText=='In')?'Out':'In';
}
ZoomInClick(){
this.animationState = 'final';
}
ZoomOutClick(){
this.animationState = 'initial';
}
3. animationdemo.component.html
<div>
<img (mouseover)="ZoomInClick()"
(mouseout)="ZoomOutClick()" [@zoom]="animationState"
src="assets/shoe.jpg" width="100" height="100">
</div>
</div>
</div>
Ex: Multiple Triggers
component.ts
@Component({
selector: 'app-animationsdemo',
templateUrl: './animationsdemo.component.html',
styleUrls: ['./animationsdemo.component.css'],
animations: [
trigger('zoom', [
state('initial', style(
{
'font-size':'20px',
'transform': 'rotate(0deg)'
}
)),
state('final', style({
'font-size': '80px',
'transform': 'rotate(360deg)'
})),
transition('initial=>final', animate(4000)),
transition('final=>initial', animate(3000))
]),
trigger('zoomImage', [
state('initial', style(
{
'width':'100px',
'height': '100px',
'transform': 'rotate(0deg)'
}
)),
state('final', style({
'width':'200px',
'height': '200px',
'transform': 'rotate(360deg)'
})),
transition('initial=>final', animate(4000)),
transition('final=>initial', animate(3000))
])
]
})
export class AnimationsdemoComponent implements OnInit {
animationState:any = 'initial';
buttonText:string = 'In';
constructor() { }
ngOnInit(): void {
}
ZoomClick(){
this.animationState =
(this.animationState=='initial')?'final':'initial';
this.buttonText = (this.buttonText=='In')?'Out':'In';
}
ZoomInClick(){
this.animationState = 'final';
}
ZoomOutClick(){
this.animationState = 'initial';
}
component.html
<div>
<h1 [@zoom]="animationState">Welcome to
Angular</h1>
</div>
</div>
</div>
End of Components
Angular Pipes
============
- Angular is used in front end to consume data from API and
present in UI.
- Data comes from various sources, Angular can't present the
data exactly how it is defined.
- You have to Transform data and present in UI.
- Pipes are used to Transform data.
- Pipes are used to format the data.
- Angular provides pre-defined Pipes [Built-in Pipes]
AsyncPipe
UpperCasePipe
LowerCasePipe
TitleCasePipe
NumberPipe
CurrencyPipe
SlicePipe
PercentPipe
JsonPipe
i18nSelectPipe
i18nPluralPipe
DatePipe
- Angular also allows to create Custom Pipes
- Angular Pipes are classified into 2 groups by developers
a) Pure Pipe [ Only Format Changes ]
b) Impure Pipe [ Can Change Data]
- Angular Pipe can be parameter less or parameterized.
Syntax:
data | pipeName:parameter1:parameter2
Pipe Architecture
=============
- Every Pipe is a class that implements "PipeTransform"
contract.
@Pipe({
name: 'pipename'
})
export class PipeName implements PipeTransform
{
transform(){ }
}
sentencecase.pipe.ts
@Pipe({
name: 'sentencecase'
})
export class SentenceCasePipe implements PipeTransform
{
transform(value:any) {
let firstChar = value.charAt(0);
let restChars = value.substring(1);
let sentence =
firstChar.toUpperCase()+restChars.toLowerCase();
return sentence;
}
}
declarations: [
SentenceCasePipe
]
5. pipedemo.component.ts
6. pipedemo.component.html
<h1>{{title | sentencecase}}</h1>
Note: You can create and add pipe into project by using CLI
commands
@Pipe({
name: 'sorting'
})
export class SortingPipe implements PipeTransform {
transform(list:any, reverse?:boolean) {
list.sort();
if(reverse==true){
list.sort();
list.reverse();
}
return list;
}
3. pipedemo.component.ts
4. pipedemo.component.html
<div class="container-fluid">
<h2>Cities</h2>
<ol>
<li *ngFor="let item of cities|sorting:true">
{{item}}
</li>
</ol>
</div>
Note : You can chain pipes.
Ex:
product = {
Name: 'JBL Speaker',
Price: 4500.50,
Mfd: new Date('2020/02/10')
};
{{product.Name | lowercase}}
TitleCasePipe titlecase It converts every word first char to
uppercase.
Ex:
product = {
Name: 'JBL Speaker',
Price: 4500.50,
Mfd: new Date('2020/02/10')
};
{{product.Name | titlecase}}
DecimalPipe number It is used to display numeric value
with thousands separator and
fractions.
Syntax:
{{data | number:
{minIntegerDigits}:{minFractionDigits}
-{maxFractionDigits} }}
Ex:
product = {
Name: 'JBL Speaker',
Price: 4500.50,
Mfd: new Date('2020/02/10')
};
{{product.Price | number:’4.2-4’}}
CurrencyPipe currency It is similar to decimal pipe but have a
currency symbol to display.
Syntax:
{{data | currency: ‘CurrencyFormat’:
‘digitsInfo’}}
Currency Format you can define
“USD, INR, etc.”
You can also define literals “₹”
Ex:
product = {
Name: 'JBL Speaker',
Price: 4500.50,
Mfd: new Date('2020/02/10')
};
{{ product.Price | currency: ‘INR’ }}
{{ product.Price | currency: ‘₹’
}}
DatePipe date It is used for displaying date and time
value in various date and time
formats.
Ex:
product = {
Name: 'JBL Speaker',
Price: 4500.50,
Mfd: new Date('2020/02/10')
};
Syntax:
{{ data | date: ‘MM-dd-yyyy’}}
{{product.Mfd | date: 'MMMM-dd-
yyyy'}}
PercentPipe percent Transforms a number into percentage
string.
Syntax:
{{data | percent: ‘digitsInfo’ }}
Ex:
product = {
Name: 'JBL Speaker',
Price: 4500.50,
Mfd: new Date('2020/02/10'),
Sales: 0.259
};
{{product.Sales | percent:'2.2-2'}}
SlicePipe slice It creates a new array or string
containing subset of the elements.
It can extract values based on
specified index and return an array.
{{ collection |
slice:startIndex:endIndex }}
Ex:
products = ['TV', 'Mobile', 'Speaker',
'Shoe', 'Shirt'];
<ol>
<li *ngFor="let item of products |
slice:1:3">
{{item}}
</li>
</ol>
JsonPipe json It converts the data into JSON format,
so that can transport to server-side
services.
Ex:
product = {
Name: 'JBL Speaker',
Price: 4500.50,
Mfd: new Date('2020/02/10'),
Sales: 0.259
};
<div>
<pre>
{{product | json}}
</pre>
</div>
KeyValuePipe keyvalue It allows to read the properties and
values from a collection.
“Key” is used to access the keys or
properties
“Value” is used to access the values.
You can configure on a collection like
“Array or Map”.
Ex:
data: {[key:number]:string} = {
1001: 'Samsung TV',
1002: 'Nike Casuals'
};
products = ['TV', 'Mobile', 'Speaker',
'Shoe', 'Shirt'];
<div class="container-fluid">
<h2>Array</h2>
<ol style="list-style: none;">
<li *ngFor="let item of products |
keyvalue">
[{{item.key}}] {{item.value}}
</li>
</ol>
<h2>Map</h2>
<ol style="list-style: none;">
<li *ngFor="let item of data |
keyvalue">
{{item.key}} - {{item.value}}
</li>
</ol>
</div>
I18nSelectPipe i18select • i18 is community of Angular.
• It designed SelectPipe.
• It is a generic selector that can
make decision dynamically
according to the state or values
and define result when the
relative condition is matching.
• In early version we have to
depend on lot of iterations and
conditions.
Syntax:
{{value_expression |
i18select:mapping}}
• It is an impure pipe.
Ex:
export class PipedemoComponent{
products = [
{Name: 'Samsung TV', City: 'Delhi'},
{Name: 'Nike Casuals', City:
'Hyderabad'},
{Name: 'Mobile', City: 'Delhi'},
{Name: 'Shirt', City: 'Goa'}
];
statusMessage = {
'Hyderabad': 'Delivery in 2 Days',
'Delhi': 'Delivery on same Day',
'Mumbai': 'Not Deiverable',
'other': 'Unknow - We Will Update'
};
}
<div class="container-fluid">
<h2>Products Status</h2>
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>City</th>
<th>Delivery Status</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of
products">
<td>{{item.Name}}</td>
<td>{{item.City}}</td>
<td>{{item.City |
i18nSelect:statusMessage}}</td>
</tr>
</tbody>
</table>
</div>
I18PluralPipe i18plural • As per coding standards we use
plural name of multiple items or
collection and singular name for
one object.
Syntax:
product = {};
products = [];
• Plural Pipe can identify whether
the object comprises of single or
multiple value and define a
plural name dynamically.
• It can get collection count and
display messages according to
count.
• It uses a map to verify the
values.
Syntax:
{{collection.length |
i18plural:keyValueCollection}}
Ex:
• Go to “app.module.ts” and import following modules
import { MatIconModule } from '@angular/material/icon';
import { MatBadgeModule } from '@angular/material/badge';
imports: [
MatIconModule,
MatBadgeModule
],
• Pluraldemo.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-pluraldemo',
templateUrl: './pluraldemo.component.html',
styleUrls: ['./pluraldemo.component.css']
})
export class PluraldemoComponent{
notifications = [];
notificationsMap: {[key:string]:string} = {
'=0': 'No Missed Calls', '=1': 'One Missed Call', 'other': '#
Missed Calls'
};
showCalls = false;
ManagerClick(){
this.notifications.push('Call From Manager');
}
AdminClick(){
this.notifications.push('Call from Admin');
}
GetMissedCalls() {
this.showCalls = true;
}
}
• Pluraldemo.component.html
<div class="container-fluid">
<h2>Plural Demo</h2>
<div class="form-group">
<button (click)="ManagerClick()">Call From
Manager</button>
<button (click)="AdminClick()">Call From Admin</button>
</div>
<mat-icon
matBadge="{{notifications.length}}">phone</mat-icon>
<span style="cursor: grab;" (click)="GetMissedCalls()">
{{notifications.length | i18nPlural:notificationsMap}}
</span>
<div *ngIf="showCalls" class="form-group">
<h3>Missed Calls</h3>
<ul>
<li *ngFor="let item of notifications">
{{item}}
</li>
</ul>
</div>
</div>
Custom Pipe
• You can create your own pipe that can transform data.
• To create a pipe, you need create a class that implement
“PipeTranform”
• You have to configure the functionality by using “transform()”
Ex:
• Add a new folder
“CustomPipes”
• Add a new file
Sentencecase.pipe.ts
import { PipeTransform, Pipe } from '@angular/core';
@Pipe(
{name: 'sentencecase'}
)
export class SentenceCasePipe implements PipeTransform {
transform(str){
let firstChar = str.charAt(0);
let restChars = str.substring(1);
let sentence = firstChar.toUpperCase() +
restChars.toLowerCase();
return sentence;
}
}
• Go to “app.module.ts” and register the pipe in declarations
declarations : [
SentenceCasePipe
]
• Apply for your content
msg = “wELCome TO AGulaR”;
{{ msg | sentencecase }}
Try:
• Create a pipe for sorting and printing the list of values from
array.
Somecollection = [ ]
Angular Services
• Service is a pre-defined business logic which can be reused in
the application by injecting into any component.
• Service is a collection of Factories.
• Factory is a collection of related type of functions.
• You can inject a factory into any component in order to use the
functionality.
• Factory uses a single call mechanism. Every time when you
want to use a function you need an object to create.
[Disconnected – Discrete]
• Service uses a Single Ton mechanism. Object is created for first
request and the same object is used across any number of
requests. [Connected – Continuous]
• Angular service is a class with a set of functions [service
methods] that return any specific functionality.
• Angular service implements the functionality from
“Injectable()” directive.
• Injectable allows service to use a single ton mechanism so that
it can be injected into any component.
Syntax:
Import { Injectable } from ‘@angular/core’;
@Injectable(
providedIn: ‘root’
) // decorator for service
export class ServiceName {
serviceMethod() { }
}
• You have to register a service in order use in application.
Services are registered in “app.module.ts” at
providers: [ ServiceName ]
• CLI command for generating service:
> ng g service serviceName –skipTests
Ex:
• Add a new file into “app” folder
“captcha.service.ts”
@Injectable({
providedIn: 'root'
})
export class CaptchaService {
public GenerateCode() {
let a = Math.random() * 10;
let b = Math.random() * 10;
let c = Math.random() * 10;
let d = Math.random() * 10;
let e = Math.random() * 10;
let f = Math.random() * 10;
let code = `${Math.round(a)} ${Math.round(b)}
${Math.round(c)} ${Math.round(d)} ${Math.round(e)}
${Math.round(f)}`;
return code;
}
}
• Register service in “app.module.ts”
providers: [ CaptchaService ],
<div class="box">
<h2>{{title}}</h2>
<div class="group">
<label>User Name</label>
<div>
<input type="text">
</div>
</div>
<div class="group">
<label>Password</label>
<div>
<input type="password">
</div>
</div>
<div class="group">
<label>Verify Code</label>
<div>
<button (click)="NewCode()">{{code}} <span class="fa fa-
sync-alt"></span></button>
</div>
</div>
<div class="group">
<button>Login</button>
</div>
</div>
• login.component.css
.box {
justify-content: center;
align-items: center;
margin:auto;
width:300px;
border:2px solid darkcyan;
box-shadow: 2px 2px 3px darkcyan;
padding: 10px;
margin-top: 20px;
}
.group {
margin-bottom: 20px;
}
button {
background-color: darkcyan;
color:white;
}
Ex: Data
• Generate a service
• ng g service data --skipTests
• data.service.ts
@Injectable()
export class DataService {
public GetProducts(){
return [
{Name: 'JBL Speaker', Price: 45000.55, Photo:
'assets/jblspeaker.jpg', Category: 'Electronics'},
{Name: 'Earpods', Price: 4000.55, Photo:
'assets/earpods.jpg', Category: 'Electronics'},
{Name: 'Nike Casuals', Price: 9000.55, Photo:
'assets/shoe.jpg', Category: 'Footwear'},
{Name: 'Lee Cooper Boot', Price: 3000.55, Photo:
'assets/shoe1.jpg', Category: 'Footwear'},
{Name: 'Shirt', Price: 2600.55, Photo: 'assets/shirt.jpg',
Category: 'Fashion'},
{Name: 'Jeans', Price: 2000.55, Photo: 'assets/jeans.jpg',
Category: 'Fashion'}
];
}
}
• Goto “app.module.ts” and register service
providers: [ CaptchaService, DataService ],
• Productslist.component.ts
@Component({
selector: 'app-productslist',
templateUrl: './productslist.component.html',
styleUrls: ['./productslist.component.css']
})
export class ProductslistComponent implements OnInit {
constructor(private data: DataService){
}
public products = [];
ngOnInit() {
this.products = this.data.GetProducts();
}
public ElectronicCount =
this.products.filter(x=>x.Category=='Electronics').length;
public FootwearCount =
this.products.filter(x=>x.Category=='Footwear').length;
public FashionCount =
this.products.filter(x=>x.Category=='Fashion').length;
public selectedCategoryValue = 'All';
public onFilterCategoryChanged(selectedCategoryName) {
this.selectedCategoryValue = selectedCategoryName;
}
}
HttpClient Service
==============
- fetch() is a JavaScript method for interacting with API.
- HttpClient is a service provided by Angular for interacting
with API.
HttpClient:
- It returns data in JSON format.
- It uses "RxJS" library, which makes HttpClient
Asynchronous.
- It uses unblocking technique.
- It can handle CORS
- It is faster than fetch()
- HttpClient service is defined under "HttpClientModule" of
"@angular/common/http" library
Syntax:
GetProducts:Observable<T>() {
GetProduct.subscribe(data=> { })
Ex:
1. Go to "app.module.ts"
imports: [
HttpClientModule
]
"Fakestoreapi.service.ts"
@Injectable({
providedIn: 'root'
})
export class FakestoreapiService
{
constructor(private http: HttpClient){}
GetCategories():Observable<string[]>{
return
this.http.get<string[]>('http://fakestoreapi.com/products/catego
ries HYPERLINK
"http://fakestoreapi.com/products/categories&"& HYPERLINK
"http://fakestoreapi.com/products/categories’);
}
GetProducts():Observable<any[]>{
return
this.http.get<any[]>('http://fakestoreapi.com/products
HYPERLINK "http://fakestoreapi.com/products&"&
HYPERLINK "http://fakestoreapi.com/products”);
}
}
> ng g c fakestore
4. fakestore.component.ts
@Component({
selector: 'app-fakestore',
templateUrl: './fakestore.component.html',
styleUrls: ['./fakestore.component.css']
})
export class FakestoreComponent implements OnInit {
categories:string[] = [];
products:any[] = [];
ngOnInit(): void {
this.fakestore.GetCategories().subscribe(category=>
this.categories = category );
this.fakestore.GetProducts().subscribe(product=>
this.products = product);
}
5. fakestore.component.html
<div class="container-fluid">
<div class="row">
<div class="col-3">
<div>
<label class="form-label">Select Category</label>
<div>
<select class="form-select">
<option *ngFor="let item of categories">
{{item | titlecase}}
</option>
</select>
</div>
</div>
</div>
<div class="col-9">
<div class="d-flex flex-wrap" style="height: 400px;">
<div *ngFor="let item of products" class="card m-2 p2"
style="width: 200px;">
<img [src]="item.image" height="150" class="card-img-
top">
<div class="card-header">
<p>{{item.title}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
- Angular Components
- Angular Pipes
- Angular Services
Angular Forms
- Form provides an UI from where user can interact with our
application.
- Angular Forms are classified into 2 types
a) Template Driven Forms
b) Model Driven Forms / Reactive Forms
<input type="text"
name="UserName" ngModel #UserName="ngModel">
<select name="City" ngModel #City="ngModel">
</select>
Syntax:
<form #frmRegister="ngForm">
<input type="text" ngModel name="UserName"
#UserName="ngModel">
</form>
Syntax:
frmRegister.value
{
"UserName:" ",
"Mobile": " "
}
frmRegister.value.UserName
frmRegister.value.Mobile
Ex:
templateform.component.ts
@Component({
selector: 'app-templateform',
templateUrl: './templateform.component.html',
styleUrls: ['./templateform.component.css']
})
export class TemplateformComponent implements OnInit
{
constructor() { }
ngOnInit(): void {
}
FormSubmit(obj:any){
alert(JSON.stringify(obj));
}
templateform.component.html
<div class="container-fluid">
<form #frmRegister="ngForm"
(ngSubmit)="FormSubmit(frmRegister.value)">
<h2>Register User</h2>
<dl>
<dt>User Name</dt>
<dd><input name="UserName" ngModel
#UserName="ngModel" type="text"></dd>
<dt>Mobile</dt>
<dd><input type="text" name="Mobile" ngModel
#Mobile="ngModel"></dd>
</dl>
<button type="submit">Register</button>
</form>
<h3>Details</h3>
<dl>
<dt>User Name</dt>
<dd>{{frmRegister.value.UserName}}</dd>
<dt>Mobile</dt>
<dd>{{frmRegister.value.Mobile}}</dd>
</dl>
</div>
Syntax:
frmRegister.pristine
frmRegister.dirty
.invalid-style {
background-color: rgb(253, 202, 202);
padding: 10px;
}
.valid-style {
background-color: rgb(198, 248, 198);
padding: 10px;
}
templateform.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-templateform',
templateUrl: './templateform.component.html',
styleUrls: ['./templateform.component.css']
})
export class TemplateformComponent implements OnInit
{
constructor() { }
ngOnInit(): void {
}
FormSubmit(obj:any){
alert(JSON.stringify(obj));
}
template.component.html
<div class="container-fluid">
<div class="row mt-3">
<div class="col-5">
<form [ngClass]="{'valid-style':frmRegister.valid,
'invalid-style':frmRegister.invalid}"
#frmRegister="ngForm"
(ngSubmit)="FormSubmit(frmRegister.value)">
<h2>Register User</h2>
<dl>
<dt>User Name</dt>
<dd><input required minlength="4"
maxlength="10" name="UserName" ngModel
#UserName="ngModel" type="text"></dd>
<dt>Mobile</dt>
<dd><input required pattern="\+91[0-9]{10}"
type="text" name="Mobile" ngModel
#Mobile="ngModel"></dd>
</dl>
<button [disabled]="frmRegister.invalid"
type="submit">Register</button>
<button *ngIf="frmRegister.dirty">Save</button>
</form>
</div>
<div class="col-7">
<h2>Validation Services</h2>
<dl>
<dt>Pritine [No Changes Detected]</dt>
<dd>{{frmRegister.pristine}}</dd>
<dt>Dirty [Changes Detected]</dt>
<dd>{{frmRegister.dirty}}</dd>
<dt>Valid [All fields Valid]</dt>
<dd>{{frmRegister.valid}}</dd>
<dt>Invalid [Any one field Invalid]</dt>
<dd>{{frmRegister.invalid}}</dd>
<dt>Submitted</dt>
<dd>{{frmRegister.submitted}}</dd>
</dl>
</div>
</div>
</div>
Syntax:
UserName.pristine
UserName.dirty
Mobile.invalid
objectName['Property']
templateform.component.html
<div class="container-fluid">
<div class="row mt-3">
<div class="col-5">
<form #frmRegister="ngForm">
<h2>Register User</h2>
<dl>
<dt>User Name</dt>
<dd><input required minlength="4"
name="UserName" ngModel #UserName="ngModel"
type="text"></dd>
<dd class="text-danger"
*ngIf="frmRegister.submitted || (UserName.touched &&
UserName.invalid)">
<span
*ngIf="UserName.errors?.['required']">User Name
Required</span>
<span
*ngIf="UserName.errors?.['minlength']">User Name too
short</span>
</dd>
<dt>Mobile</dt>
<dd><input required
pattern="\+91\d{10}" type="text" name="Mobile"
ngModel #Mobile="ngModel"></dd>
<dd class="text-danger"
*ngIf="frmRegister.submitted || (Mobile.touched &&
Mobile.invalid)">
<span
*ngIf="Mobile.errors?.['required']">Mobile
Required</span>
<span
*ngIf="Mobile.errors?.['pattern']">Invalid Mobile</span>
</dd>
</dl>
<button type="submit">Register</button>
</form>
</div>
<div class="col-7">
</div>
</div>
</div>
Template Forms
=============
Template Validation
a) Form State
pristine
dirty
valid
invalid
submitted
b) Input State
pristine
dirty
valid
invalid
touched
untouched
errors?.['required', 'minlength', 'pattern']
Custom Validations:
---------------------------
- You can write your own validation function and bind to
any HTML element.
- It requires event and property binding.
Ex:
templateform.component.ts
@Component({
selector: 'app-templateform',
templateUrl: './templateform.component.html',
styleUrls: ['./templateform.component.css']
})
export class TemplateformComponent implements OnInit
{
constructor() { }
ngOnInit(): void {
}
FormSubmit(obj:any){
alert(JSON.stringify(obj));
}
isCityInValid:boolean = true;
CityChanged(e:any){
if(e.target.value=='-1'){
this.isCityInValid = true;
} else {
this.isCityInValid = false;
}
}
isEvenInvalid:boolean = true;
VerifyEven(e:any){
if(parseInt(e.target.value)%2==0){
this.isEvenInvalid = false;
} else {
this.isEvenInvalid = true;
}
}
templateform.component.html
<div class="container-fluid">
<div class="row mt-3">
<div class="col-5">
<form #frmRegister="ngForm">
<h2>Register User</h2>
<dl>
<dt>User Name</dt>
<dd><input required minlength="4"
name="UserName" ngModel #UserName="ngModel"
type="text"></dd>
<dd class="text-danger"
*ngIf="frmRegister.submitted || (UserName.touched &&
UserName.invalid)">
<span
*ngIf="UserName.errors?.['required']">User Name
Required</span>
<span
*ngIf="UserName.errors?.['minlength']">User Name too
short</span>
</dd>
<dt>Mobile</dt>
<dd><input required
pattern="\+91\d{10}" type="text" name="Mobile"
ngModel #Mobile="ngModel"></dd>
<dd class="text-danger"
*ngIf="frmRegister.submitted || (Mobile.touched &&
Mobile.invalid)">
<span
*ngIf="Mobile.errors?.['required']">Mobile
Required</span>
<span
*ngIf="Mobile.errors?.['pattern']">Invalid Mobile</span>
</dd>
<dt>Your City</dt>
<dd>
<select (change)="CityChanged($event)"
name="City" ngModel #City="ngModel">
<option value="-1">Select Your
City</option>
<option value="Delhi">Delhi</option>
<option value="Hyd">Hyd</option>
</select>
</dd>
<dd *ngIf="isCityInValid" class="text-danger">
<span>Please Select Your City</span>
</dd>
<dt>Veriy Code [Enter Any Even Number]</dt>
<dd>
<input (blur)="VerifyEven($event)"
name="Even" ngModel #Even="ngModel" type="text">
</dd>
<dd class="text-danger" *ngIf="isEvenInvalid">
<span>Code Required - Must be an Even
Number</span>
</dd>
</dl>
<button type="submit">Register</button>
</form>
</div>
<div class="col-7">
</div>
</div>
</div>
.ng-pristine
.ng-dirty
.ng-valid
.ng-invalid
.ng-touched
.ng-untouched
Syntax:
form.ng-pristine {
}
input.ng-valid {
}
select.ng-dirty {
Ex:
templateform.component.css
input.ng-valid {
border:1px solid green;
box-shadow: 2px 2px 2px green;
}
input.ng-invalid {
border:1px solid red;
box-shadow: 2px 2px 2px red;
}
form.ng-invalid {
background-color: lightpink;
padding: 20px;
}
form.ng-valid {
background-color: lightgreen;
padding: 20px;
}
Draw Backs
----------------
- Tightly coupled
- Hard to Test
- Hard to Extend
- Heavy on UI
- It will reduce the initial load time but response time will
be slow.
- Separation concerns
FormControl:
- It is the base class for all form elements like button,
textbox, checkbox, radio, listbox etc..
Name.value
Name.pristine
Name.dirty etc..
Template Form:
<input type="text"
name="Name" ngModel #Name="ngModel">
Model Form:
<input type="text" formControlName="Name">
<body> Valid
<form>
</form>
<form>
</form>
</body>
<body> Invalid
<form>
<form>
</form>
</form>
</body>
<form>
<div [form]>
</div>
</form>
Syntax:
frmRegister = new FormGroup({
// controls
});
Syntax:
<div [formGroup]="frmRegister"> </div>
<form [formGroup]="frmRegister"> </div>
Syntax:
Name : new FormControl('value', [ Validators ]);
Syntax:
<input type="text" formControlName="Name">
<select forControlName="Name">
<input type="checkbox" formControlName="Name">
Ex:
1. Import "ReactiveFormsModule" in "app.module.ts"
imports : [
ReactiveFormsModule
]
- Every ReactiveForm Control is "Async"
- It allows to update of post only specific portion of form.
- It implicitly uses "Ajax".
- FormGroup provide "patchValue()" that can update
asyncrhonously.
Syntax:
<form [formGroup]="ParentForm">
<input type="text" formControlName="Name">
<div formGroupName="ChildForm">
<input type="text" formControlName="Price">
</div>
</form>
Ex:
modelform.component.ts
@Component({
selector: 'app-modelform',
templateUrl: './modelform.component.html',
styleUrls: ['./modelform.component.css']
})
export class ModelformComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
FormSubmit(obj:any){
alert(JSON.stringify(obj));
}
UpdatePartial(){
this.frmRegister.patchValue({
Name: 'Samsung TV',
frmStock: {
City: 'Hyd'
}
})
}
modelform.component.html
<div class="container-fluid">
<form [formGroup]="frmRegister"
(submit)="FormSubmit(frmRegister.value)" class="bg-warning
p-3 w-75">
<h2>Basic Details</h2>
<dl>
<dt>Name</dt>
<dd><input formControlName="Name"
type="text"></dd>
<dt>Price</dt>
<dd><input type="text"
formControlName="Price"></dd>
<div formGroupName="frmStock" class="bg-info p-3
w-25">
<h3>Stock Details</h3>
<dl>
<dt>Status</dt>
<dd><input type="checkbox"
formControlName="Status"> Available</dd>
<dt>City</dt>
<dd>
<select formControlName="City">
<option>Delhi</option>
<option>Hyd</option>
<option>Chennai</option>
</select>
</dd>
</dl>
</div>
</dl>
<button>Register</button>
<button (click)="UpdatePartial()" type="button">Update
Partial</button>
</form>
</div>
Syntax:
frmRegister:any;
ngOnInit() {
this.frmRegister = this.fb.group({
Name: this.fb.control(''),
frmStock: this.fb.group({
Status: this.fb.control(true)
})
})
}
Ex:
modelform.component.ts
frmRegister:any;
ngOnInit(): void {
this.frmRegister = this.fb.group({
Name: this.fb.control(''),
Price: this.fb.control(0),
frmStock: this.fb.group({
Status: this.fb.control(true),
City: this.fb.control('Delhi')
})
})
}
FormSubmit(obj:any){
alert(JSON.stringify(obj));
}
UpdatePartial(){
this.frmRegister.patchValue({
Name: 'Samsung TV',
frmStock: {
City: 'Hyd'
}
})
}
}
modelform.component.html
<div class="container-fluid">
<form [formGroup]="frmRegister"
(submit)="FormSubmit(frmRegister.value)" class="bg-warning
p-3 w-75">
<h2>Basic Details</h2>
<dl>
<dt>Name</dt>
<dd><input formControlName="Name"
type="text"></dd>
<dt>Price</dt>
<dd><input type="text"
formControlName="Price"></dd>
<div formGroupName="frmStock" class="bg-info p-3
w-25">
<h3>Stock Details</h3>
<dl>
<dt>Status</dt>
<dd><input type="checkbox"
formControlName="Status"> Available</dd>
<dt>City</dt>
<dd>
<select formControlName="City">
<option>Delhi</option>
<option>Hyd</option>
<option>Chennai</option>
</select>
</dd>
</dl>
</div>
</dl>
<button>Register</button>
<button (click)="UpdatePartial()" type="button">Update
Partial</button>
</form>
</div>
Ex:
modelform.component.ts
@Component({
selector: 'app-modelform',
templateUrl: './modelform.component.html',
styleUrls: ['./modelform.component.css']
})
export class ModelformComponent implements OnInit {
frmRegister:any;
ngOnInit(): void {
this.frmRegister = this.fb.group({
Name: this.fb.control(''),
Price: this.fb.control(0),
frmStock: this.fb.group({
Status: this.fb.control(true),
City: this.fb.control('Delhi')
}),
newControls: this.fb.array([this.fb.control('')])
})
}
get NewControls(){
return this.frmRegister.get('newControls') as FormArray;
}
AddClick(){
this.NewControls.push(this.fb.control(''));
}
RemoveClick(i:number){
this.NewControls.removeAt(i);
}
FormSubmit(obj:any){
alert(JSON.stringify(obj));
}
UpdatePartial(){
this.frmRegister.patchValue({
Name: 'Samsung TV',
frmStock: {
City: 'Hyd'
}
})
}
modelform.component.html
<div class="container-fluid">
<form [formGroup]="frmRegister"
(submit)="FormSubmit(frmRegister.value)" class="bg-warning
p-3 w-75">
<h2>Basic Details</h2>
<dl>
<dt>Name</dt>
<dd><input formControlName="Name"
type="text"></dd>
<dt>Price</dt>
<dd><input type="text"
formControlName="Price"></dd>
<dt>Upload Photo <button type="button"
(click)="AddClick()" class="btn btn-link">Add
More</button></dt>
<dd *ngFor="let item of NewControls.controls; let
i=index">
<input type="file" name="i">
<button (click)="RemoveClick(i)" class="btn btn-
link">Remove</button>
</dd>
<div formGroupName="frmStock" class="bg-info p-3
w-25">
<h3>Stock Details</h3>
<dl>
<dt>Status</dt>
<dd><input type="checkbox"
formControlName="Status"> Available</dd>
<dt>City</dt>
<dd>
<select formControlName="City">
<option>Delhi</option>
<option>Hyd</option>
<option>Chennai</option>
</select>
</dd>
</dl>
</div>
</dl>
<button>Register</button>
<button (click)="UpdatePartial()" type="button">Update
Partial</button>
</form>
</div>
Syntax:
<input type="text" required minlength="4" pattern="">
Syntax:
new FormControl('value', [Validators.required]);
control('value', [Validators.required]);
Syntax:
this.frmRegister = fb.group({
Name: fb.control(' ', [Validators.required,
Validators.minlength(4)])
})
get Name() {
retrun this.frmRegister.get('Name') as FormControl;
}
Ex:
modelform.component.ts
@Component({
selector: 'app-modelform',
templateUrl: './modelform.component.html',
styleUrls: ['./modelform.component.css']
})
export class ModelformComponent implements OnInit {
frmRegister:any;
ngOnInit(): void {
this.frmRegister = this.fb.group({
Name: this.fb.control('',[Validators.required,
Validators.minLength(4)]),
Price: this.fb.control(0),
frmStock: this.fb.group({
Status: this.fb.control(true),
City: this.fb.control('Delhi')
}),
newControls: this.fb.array([this.fb.control('')])
})
}
get Name() {
return this.frmRegister.get('Name') as FormControl;
}
get NewControls(){
return this.frmRegister.get('newControls') as FormArray;
}
AddClick(){
this.NewControls.push(this.fb.control(''));
}
RemoveClick(i:number){
this.NewControls.removeAt(i);
}
FormSubmit(obj:any){
alert(JSON.stringify(obj));
}
UpdatePartial(){
this.frmRegister.patchValue({
Name: 'Samsung TV',
frmStock: {
City: 'Hyd'
}
})
}
modelform.component.html
<div class="container-fluid">
<form [formGroup]="frmRegister"
(submit)="FormSubmit(frmRegister.value)" class="p-3 w-75">
<h2>Basic Details</h2>
<dl>
<dt>Name</dt>
<dd><input formControlName="Name"
type="text"></dd>
<dd class="text-danger" *ngIf="Name.touched &&
Name.invalid">
<span *ngIf="Name.errors?.['required']">Name
Required</span>
<span *ngIf="Name.errors?.['minlength']">Name too
short.. min 4 chars</span>
</dd>
<dt>Price</dt>
<dd><input type="text"
formControlName="Price"></dd>
<dt>Upload Photo <button type="button"
(click)="AddClick()" class="btn btn-link">Add
More</button></dt>
<dd *ngFor="let item of NewControls.controls; let
i=index">
<input type="file" name="i">
<button (click)="RemoveClick(i)" class="btn btn-
link">Remove</button>
</dd>
<div formGroupName="frmStock" class="bg-info p-3
w-25">
<h3>Stock Details</h3>
<dl>
<dt>Status</dt>
<dd><input type="checkbox"
formControlName="Status"> Available</dd>
<dt>City</dt>
<dd>
<select formControlName="City">
<option>Delhi</option>
<option>Hyd</option>
<option>Chennai</option>
</select>
</dd>
</dl>
</div>
</dl>
<button>Register</button>
<button (click)="UpdatePartial()" type="button">Update
Partial</button>
</form>
</div>
Angular Routing
----------------------
- Web Applications follow various techniques in building
application
a) Model Binding
b) Data Binding
c) Event Binding
d) Style Binding
e) Caching
f) Routing etc..
http://www.amazon.in/electronics.jsp?category=mobiles
HYPERLINK
"http://www.amazon.in/electronics.jsp?category=mobiles&bran
d=samsung&minPrice=10000"& HYPERLINK
"http://www.amazon.in/electronics.jsp?category=mobiles&bran
d=samsung&minPrice=10000"brand=samsung HYPERLINK
"http://www.amazon.in/electronics.jsp?category=mobiles&bran
d=samsung&minPrice=10000"& HYPERLINK
"http://www.amazon.in/electronics.jsp?category=mobiles&bran
d=samsung&minPrice=10000"minPrice=10000
With routing
http://www.amazon.in/electronics/mobiles/samsung/10000
Server Side:
fakestoreapi.com/products?id=2
fakestoreapi.com/products/2
Route and Route Parameters
Angular Routing
----------------------
- The classes required for configuring routes
- RouterModule
- Routes
- These are defined in "@angular/router"
- "RouterModule" provides set of properties and methods to
export and import routes for application.
- "Routes" is used to configure RouteTable, which comprises
of collection of routes.
Ex:
1. Create a new application in workspace
"app-routing.module.ts"
@NgModule({
imports : [RouterModule.forRoot(routes)],
exports : [RouterModule]
})
imports: [
BrowserModule,
AppRoutingModule,
RouterModule
],
Syntax:
- Design Navigation in
"app.component.html"
- Routing comprises of 2 elements in page
a) <router-outlet>
b) routerLink
2. home.component.html
3. categories.component.ts
@Component({
selector: 'app-categories',
templateUrl: './categories.component.html',
styleUrls: ['./categories.component.css']
})
export class CategoriesComponent implements OnInit {
categories:any[] = [];
constructor() { }
ngOnInit(): void {
fetch('http://fakestoreapi.com/products/categories
HYPERLINK "http://fakestoreapi.com/products/categories&"&
HYPERLINK
"http://fakestoreapi.com/products/categories&"#39;)
.then(response=>response.json())
.then(data=> {
this.categories = data;
})
}
}
4. categories.component.html
<h2>Categories</h2>
<ol>
<li *ngFor="let item of categories">
{{item|titlecase}}
</li>
</ol>
5. notfound.component.ts
@Component({
selector: 'app-notfound',
templateUrl: './notfound.component.html',
styleUrls: ['./notfound.component.css']
})
export class NotfoundComponent implements OnInit {
location:any;
constructor() { }
ngOnInit(): void {
this.location = location.pathname;
}
6. notfound.component.html
<h2>Not Found</h2>
<p>Page you requested <code>{{location}}</code> - Not
Found</p>
7. Go to "app.component.html"
<div class="container-fluid">
<header class="bg-danger text-white text-center mt-2">
<h1><span class="bi bi-cart2"></span> Flipkart
Shopping</h1>
</header>
<section>
<div class="row">
<div class="col-3">
<ul class="list-unstyled">
<li class="mb-3"><a class="btn btn-danger w-100"
routerLink="home">Home</a></li>
<li class="mb-3"><a class="btn btn-danger w-100"
routerLink="categories">Categories</a></li>
</ul>
</div>
<div class="col-9">
<router-outlet></router-outlet>
</div>
</div>
</section>
</div>
8. Go to "app-routing.module.ts"
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Route Parameters
==============
- A route parameter allows to store data in URL and transfer
across components in routing.
- Route parameter allows to query any content directly from
URL.
- Route is defined with parameters by using path
{ path: 'home/:param1/:param2/:param3..' }
Syntax:
http://localhost:4200/details/1/Mobile
Syntax:
constructor(private route: ActivatedRoute) { }
ProductId:any;
Name:any;
ngOnInit() {
this.ProductId = this.route.snapshot.paramMap.get("id");
}
Syntax:
{ path: 'parent', component : ParentComponent,
children: [
{path: 'child', component: ChildComponent }
]
}
<parentcomponent>
details
<router-outlet> </router-outlet>
</parentcomponent>
Routing Complete Example - ZIP
for Flipkart Example.
- MongoDB Database
- Express Middleware
- Angular Front End
- Node Server Side - API
Database
1. Download and Install MongoDB database on your PC
https://www.mongodb.com/try/download/community
5. MongoDB Terminology
RDBMS MongoDB
------------------------------------------------------
Database Database
Table Collection
Records Document
Field Field
Joins Embedded Documents
{
"UserId": "john_nit",
"UserName": "John",
"Password": "john@12",
"Age": 22,
"Email": "john@gmail.com",
"Mobile": "+919876543210"
}
10. Click Insert
Summary:
Database Name : demodb
Table Name [Collection] : tblusers
Connection String : mongodb://127.0.0.1:27017
"www.connectionstrings.com"
app.listen(8080);
console.log("Server Started : http://127.0.0.1:8080");
Route Guard and Cookie
Route Guards
- Allows to configure access restriction for any specific route
path in application.
- Route Guards are configured at various levels, like
a) To Activate a route
b) To exit a route
c) To exit a child route etc..
- These route phases are reffered as "Route Cycle Hooks"
Lazy Routes
Deployment
Testing
Lazy Routes and Testing
Lazy Routes
- Lazy loading is a software design pattern that allows to load
only the content that is requested.
- Eager Loading loads the modules and library even when you
are not using them.
- It improves the performance of application.
- Application specific framework.
- Light weight application.
Syntax:
{ path : 'register' component: RegisterComponent }
Note: Angular can implement lazy loading for routes when you
configure application with various modules.
Ex:
1. Create new Application
3. Go to app.component.html
<div>
<a routerLink="personal">Personal Banking</a>
<span>|</span>
<a routerLink="nri">NRI</a>
<span>|</span>
<a routerLink="agri">AGRI-Govt.India</a>
</div>
<div style="margin-bottom: 20px;">
<router-outlet></router-outlet>
</div>
- Test Methods
describe()
expect()
toBe(),
toBeTruthy()
toBeEqual()
> ng g c home
home.component.ts
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
CalculateTotal(qty:number, price:number){
return qty * price;
}
Title(str:string) {
return str;
}
}
home.component.spec.ts
describe('HomeComponentTest', function(){
it('Total Test', function(){
expect(component.CalculateTotal(2,4000)).toBe(12000);
})
it('Title Test', function(){
expect(component.Title('HDFC Home')).toBe('HDFC
Home');
})
})
https://firebase.google.com/
3. Go to Firebase "Console"
Step-1:
- Click "Create New Project"
- Specify Name for project
"angular-fakeshop"
Step-2:
- Select Cloud Services
- Enable Analytics
Step-3
- Select Account
- Default Firebase Account
C:\>firebase login
6. Open your angular project and build for production (go live)
https://angular-fakeshop.web.app
[it will copy all files and folders of 'dist' into cloud]
Domain:
https://angular-fakeshop.firebaseapp.com/home