Angular is a TypeScript-based free and open-source single-page web application framework. It is developed by Google. Angular is a web framework that empowers developers to build fast, reliable applications. Angular provides solid platform, tools, APIs, and libraries to simplify and streamline your development workflow. You need basic knowledge of OOP, Javascript, TypeScript, HTML & CSS to build an Angular application.
Component is the main block of an Angular Application. A Component contains the definition
of the View and the data that defines how the View looks and behaves. The Angular Components are
plain javascript classes and defined using. @component Decorator. This Decorator provides
the component with the View to display & Metadata about the class.
The component contains selector, templateUrl, styleUrls etc.
@Component({
selector: 'selector-name', // selector for
templateUrl: './home.component.html', templateUrl for HTML template
styleUrls: ['./home.component.scss'] // styleUrls for CSS
})
Angular provides many Built-in directives such as NgClass, NgStyle, NgModel, NgIf, NgFor, NgSwitch etc. There are two types of directives Attribute Directives and Structural Directives. NgClass, NgStyle, NgModel are the part of Attribute Directives and NgIf, NgFor, NgSwitch are the part of Structural Directives. Attribute directives let us change how things are rendered in the DOM. Structural directive lets us change DOM layout by adding or removing DOM elements.
Attribute directives provides the functionality of rendering the DOM. NgClass, NgStyle, NgModel are the Attribute Directives in Angular.
---Example of ngClass Attribute Directive--- <
div [ngClass]="isHero ? 'hero' : ''">{{person.name}}<
/div> <
!--Example of ngStyle Attribute Directive--
> <
div [ngStyle]="currentStyles">Example of ngStyle.<
/div> ---TS file--- this.currentStyles = { 'font-style': 'italic', 'font-weight': 'bold', 'font-size': '12px' }; <
---Example of ngModel Attribute Directive---
> <
input [(ngModel)]="currentItem.name" id="example-ngModel">
Structural Directive allow to change DOM layout by adding or removing DOM elements. NgIf, NgFor, NgSwitch are the Structural Directives in Angular.
---Example of NgIf Structural Directive--- <
div *ngIf="hero">{{hero.name}}<
/div> ---Example of ngFor Structural Directive--- <
div *ngFor="let item of items">{{item.name}}<
/div> ---Example of ngSwitch Structural Directive--- <
div [ngSwitch]="currentItem.feature"> <
app-stout-item *ngSwitchCase="'stout'" [item]="currentItem">
app-stout-item> <
app-device-item *ngSwitchCase="'slim'" [item]="currentItem">
app-device-item> <
app-lost-item *ngSwitchCase="'vintage'" [item]="currentItem">
app-lost-item> <
app-best-item *ngSwitchCase="'bright'" [item]="currentItem">
app-best-item> <
app-unknown-item *ngSwitchDefault [item]="currentItem">
app-unknown-item> <
/div>
1. To create custom directive execute below command.
ng generate directive < directive name >
---Example of creating highlight directive---
PS E:\application\angular-mainapp\mainapp> ng generate directive highlight
CREATE src/app/highlight.directive.spec.ts (236 bytes)
CREATE src/app/highlight.directive.ts (147 bytes)
UPDATE src/app/app.module.ts (1452 bytes)
Angular CLI will be created a highlight.directive.ts file in the src/app folder.
The corresponding test file will be created as src/app/highlight.directive.spec.ts,
and declares the directive
class in the AppModule.
2. Inject ElementRef in the Custom created directive. ElementRef has direct access to the host DOM element through its nativeElement property.
src/app/highlight.directive.ts
import { Directive , ElementRef} from '@angular/core'; @Directive({ selector: '[appHighlight]' }) export class HighlightDirective { constructor(private el: ElementRef) { this.el.nativeElement.style.backgroundColor = 'yellow'; } } ---In HTML Declare directive--- <
p appHighlight>HighlightDirective Example Text!<
/p>
HostListener provides the functionality to capture of DOM event to listen and provides a handler method to run when that event occurs.
import { Directive , ElementRef, HostListener} from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onMouseEnter() {
this.highlight('yellow');
}
@HostListener('mouseleave') onMouseLeave() {
this.highlight('');
}
@HostListener('mouseenter') onMouseEnter() {
this.highlight(this.appHighlight || 'red');
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
You need to inject >@Input in the directive to get value from component.
import { Directive , ElementRef, HostListener, Input} from '@angular/core'; @Directive({ selector: '[highLightColor]' }) export class HighLightColor { @Input() highLightColor = ''; constructor(private el: ElementRef) {} @HostListener('mouseenter') onMouseEnter() { this.highlight(this.highLightColor || 'yellow'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; } } ---HTML Declaration--- <
h5 [highLightColor]="'red'">H5<
/h5> <
h6 highLightColor>H6<
/h6>
You need declare more than one @Input in the directive to get multiple values from component.
import { Directive , ElementRef, HostListener, Input} from '@angular/core'; @Directive({ selector: '[appHighlight]' }) export class HighlightDirective { @Input() appHighlight = ''; @Input() defaultColor = ''; constructor(private el: ElementRef) {} @HostListener('mouseenter') onMouseEnter() { console.log(this.appHighlight+"--"+this.defaultColor); this.highlight(this.defaultColor || this.appHighlight || 'yellow'); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; } } HTML Declaration <
h4 appHighlight defaultColor="blue">H4<
/h4> <
h5 [highLightColor]="'red'">H5<
/h5> <
h6 highLightColor>H6<
/h6>
Pipes are simple functions to use in template to accept an input value and return a transformed value.
Angular provides many Built-in Pipes such as DatePipe, UpperCasePipe, LowerCasePipe, CurrencyPipe, DecimalPipe
PercentPipe, AsyncPipe, JsonPipe etc.
To check the complete list of built-in pipes, see the pipes API documentation of Angular Pipes
To create a custom Pipe execute below command. ng g p <
pipe name> example: ng g p capital // capital is the pipe name. TS.file import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'capital' }) export class CapitalPipe implements PipeTransform { transform(value: any): any { if (typeof value !== 'string') { return value; } return value.charAt(0).toUpperCase() + value.slice(1); } } Declare Pipes in HTML {{
'tata' | capital }} Output: Tata
Form is the important part of application. You can submit data using Form. Angular provides two different approaches to handling user input through forms.
If you have very basic form requirements and logic that can be managed by the Template-driven forms. It could be a good fit for basic form such as signup form with few fields. It rely on directives in the template to create and manipulate the underlying object model. Template-driven forms uses ngModel to bind data and it is asynchronous in data binding.
To use Template-driven forms need to use/inject ngModel inside the form and also need to inject NgModule, FormsModule in the App Module.
Component TS File Example of emplate-driven form
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
@Component({
selector: 'app-templateformtest',
templateUrl: './templateformtest.component.html',
styleUrls: ['./templateformtest.component.scss']
})
export class TemplateformtestComponent implements OnInit, OnDestroy{
constructor() { }
submitted = false;
cities = ['Select City', 'Mumbai', 'Kolkata', 'Banglore', 'Delhi'];
model = {
name: "",
emailId: "",
mobileNumber:"",
address:"",
city: this.cities[0]
}
onSubmit() {
this.submitted = true;
}
}
HTML File Example of Template-driven form <
div class="container"> <
div [hidden]="submitted"> <
h1>Registration Form <
form (ngSubmit)="onSubmit()" #registrationForm="ngForm"> <
div class="form-group"> <
label for="name">Name<
/label> <
input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name" #name="ngModel"> <
div [hidden]="name.valid || name.pristine" class="alert alert-danger"> Name is required <
/div>{{
name.valid
}} - <
/div> <
div class="form-group"> <
label for="emailId">Email ID<
/label> <
input type="text" class="form-control" id="emailId" required [(ngModel)]="model.emailId" name="emailId" #emailId="ngModel"> <
div [hidden]="emailId.valid || emailId.pristine" class="alert alert-danger"> Email ID is required <
/div> <
/div> <
div class="form-group"> <
label for="mobileNumber">Mobile Number<
/label> <
input type="text" class="form-control" id="mobileNumber" required [(ngModel)]="model.mobileNumber" name="mobileNumber" #mobileNumber="ngModel"> <
div [hidden]="mobileNumber.valid || mobileNumber.pristine" class="alert alert-danger"> Mobile Number is required <
/div> <
/div> <
div class="form-group"> <
label for="address">Address<
/label> <
input type="text" class="form-control" id="address" required [(ngModel)]="model.address" name="address" #address="ngModel"> <
div [hidden]="address.valid || address.pristine" class="alert alert-danger"> Address is required <
/div> <
/div> <
div class="form-group"> <
label for="city">City <
select class="form-control" id="city" required [(ngModel)]="model.city" name="city" #city="ngModel"> <
option *ngFor="let city of cities" [value]="city">{{city}}<
/option> <
/select> <
div [hidden]="city.valid || city.pristine" class="alert alert-danger"> City is required <
/div> <
/div> <
button type="submit" class="btn btn-success" [disabled]="!registrationForm.form.valid">Submit<
/button> <
/form> <
/div> <
div [hidden]="!submitted"> <
h2>You submitted the following:<
/h2> <
div class="row"> <
div class="col-xs-3">Name<
/div> <
div class="col-xs-9">{{ model.name }}<
/div> <
/div> <
div class="row"> <
div class="col-xs-3">Email ID<
/div> <
div class="col-xs-9">{{ model.emailId }}<
/div> <
/div> <
div class="row"> <
div class="col-xs-3">Mobile Number<
/div> <
div class="col-xs-9">{{ model.mobileNumber }}<
/div> <
/div> <
button type="button" class="btn btn-primary" (click)="submitted=false">Edit<
/button> <
/div> <
/div>
Reactive forms are synchronous. The logic resides mainly in the typescript code. Compared to Template-driven forms, It is more robust, scalable, reusable, and testable. If forms are a key part of your application, or you're already using reactive patterns for building your application, use reactive forms.
Reactive forms use an explicit and immutable approach to managing the state of a form at a given point in time. Each change to the form state returns a new state, which maintains the integrity of the model between changes. Reactive forms are built around observable streams, where form inputs and values are provided as streams of input values, which can be accessed synchronously.
Reactive forms types
Form group provides the functionality of grouping of a fixed set of controls that you can manage together. All fields in a form will be collected within a group and a FormGroup instance provides its model value as an object.
Create a FormGroup
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
// other imports ...
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule
],
})
export class AppModule {}
component.ts file
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
@Component({
selector: 'app-reactiveform-group',
templateUrl: './reactiveform-group.component.html',
styleUrls: ['./reactiveform-group.component.scss']
})
export class ReactiveformGroupComponent {
userForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
emailId: new FormControl(''),
mobileNumber: new FormControl(''),
address: new FormControl('')
});
onSubmit(){
console.warn(this.userForm.value);
}
}
component.html file <
form [formGroup]="userForm" (ngSubmit)="onSubmit()"> <
div> <
label for="first-name">First Name: <
/label> <
input id="first-name" type="text" formControlName="firstName"> <
/div> <
div> <
label for="last-name">Last Name: <
/label> <
input id="last-name" type="text" formControlName="lastName"> <
/div> <
div> <
label for="last-name">Email ID: <
/label> <
input id="last-name" type="text" formControlName="emailId"> <
/div> <
div> <
label for="last-name">Mobile Number: <
/label> <
input id="last-name" type="text" formControlName="mobileNumber"> <
/div> <
div> <
label for="last-name">Address: <
/label> <
input id="last-name" type="text" formControlName="address"> <
/div> <
div> <
button type="submit" [disabled]="!userForm.valid">Submit<
/button> <
/div> <
/form>
Form array provides the functionality of nested form. It is a dynamic form, where you can add and remove controls at run time.
Create a Nested Form
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
// other imports ...
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule
],
})
export class AppModule {}
component.ts file
import { Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'app-reactivenestedform',
templateUrl: './reactivenestedform.component.html',
styleUrls: ['./reactivenestedform.component.scss']
})
export class ReactivenestedformComponent {
userForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
emailId: new FormControl(''),
mobileNumber: new FormControl(''),
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl(''),
}),
});
onSubmit(){
console.warn(this.userForm.value);
console.warn(this.userForm.controls.address.value);
}
}
component.html file <
form [formGroup]="userForm" (ngSubmit)="onSubmit()"> <
div> <
label for="first-name">First Name: <
/label> <
input id="first-name" type="text" formControlName="firstName"> <
/div> <
div> <
label for="last-name">Last Name: <
/label> <
input id="last-name" type="text" formControlName="lastName"> <
/div> <
div> <
label for="last-name">Email ID: <
/label> <
input id="last-name" type="text" formControlName="emailId"> <
/div> <
div> <
label for="last-name">Mobile Number: <
/label> <
input id="last-name" type="text" formControlName="mobileNumber"> <
/div> <
div formGroupName="address"> <
h2>Address <
label for="street">Street: <
/label> <
input id="street" type="text" formControlName="street"> <
label for="city">City: <
/label> <
input id="city" type="text" formControlName="city"> <
label for="state">State: <
/label> <
input id="state" type="text" formControlName="state"> <
label for="zip">Zip Code: <
/label> <
input id="zip" type="text" formControlName="zip"> <
/div> <
div> <
button type="submit" [disabled]="!userForm.valid">Submit<
/button> <
/div> <
/form>
FormBuilder API makes it easier to build reactive forms. Angular FormBuilder provides the functionality to add the FormGroup, nested FormGroup, FormArray & FormControls easily. It also allows us to set up the Validation rules for each of the controls.
Create a Nested Form
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
// other imports ...
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule
],
})
export class AppModule {}
component.ts file
import { Component } from '@angular/core';
import { FormBuilder, FormControl } from '@angular/forms';
@Component({
selector: 'app-form-builder-example',
templateUrl: './form-builder-example.component.html',
styleUrls: ['./form-builder-example.component.scss']
})
export class FormBuilderExampleComponent {
constructor(private formBuilder: FormBuilder) {}
userForm = this.formBuilder.group({
firstName: new FormControl(''),
lastName: new FormControl(''),
emailId: new FormControl(''),
mobileNumber: new FormControl(''),
address: this.formBuilder.group({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl('')
})
});
get firstname() {
return this.userForm.get('firstname');
}
get lastname() {
return this.userForm.get('lastname');
}
onSubmit(){
console.log(this.userForm.value);
}
}
component.html file <
form [formGroup]="userForm" (ngSubmit)="onSubmit()"> <
div> <
label for="first-name">First Name: <
/label> <
input id="first-name" type="text" formControlName="firstName"> <
/div> <
div> <
label for="last-name">Last Name: <
/label> <
input id="last-name" type="text" formControlName="lastName"> <
/div> <
div> <
label for="last-name">Email ID: <
/label> <
input id="last-name" type="text" formControlName="emailId"> <
/div> <
div> <
label for="last-name">Mobile Number: <
/label> <
input id="last-name" type="text" formControlName="mobileNumber"> <
/div> <
div formGroupName="address"> <
h2>Address <
label for="street">Street: <
/label> <
input id="street" type="text" formControlName="street"> <
label for="city">City: <
/label> <
input id="city" type="text" formControlName="city"> <
label for="state">State: <
/label> <
input id="state" type="text" formControlName="state"> <
label for="zip">Zip Code: <
/label> <
input id="zip" type="text" formControlName="zip"> <
/div> <
div> <
button type="submit" [disabled]="!userForm.valid">Submit<
/button> <
/div> <
/form>
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
// other imports ...
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule
],
})
export class AppModule {}
component.ts file
import { Component } from '@angular/core';
import { FormBuilder, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-form-builder-example',
templateUrl: './form-builder-example.component.html',
styleUrls: ['./form-builder-example.component.scss']
})
export class FormBuilderExampleComponent {
userForm : any;
constructor(private formBuilder: FormBuilder) {
this.userForm = this.formBuilder.group({
firstname: ['', Validators.required],
lastname: ['', [Validators.required, Validators.minLength(10)]],
emailId: [Validators.required, Validators.email],
mobileNumber: [Validators.required, Validators.minLength(10)],
address: this.formBuilder.group({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl('')
})
});
}
onSubmit(){
console.log(this.userForm.value);
if (this.userForm.dirty && this.userForm.valid) {
alert(
`Name: ${this.userForm.value.name} Email: ${this.userForm.value.email}`
);
}
}
}
component.html file <
div> <
label for="firstname">First Name <
/label> <
input type="text" id="firstname" name="firstname" formControlName="firstname"> <
div class="alert alert-danger" *ngIf="firstname.touched && firstname.errors?.required"> First Name Required. <
/div> <
/div> <
div> <
label for="lastname">Last Name <
/label> <
input type="text" id="lastname" name="lastname" formControlName="lastname"> <
div class="alert alert-danger" *ngIf="lastname.touched && lastname.errors?.required"> Last Name Required. <
/div> <
div class="alert alert-danger" *ngIf="lastname.touched && lastname.errors?.minlength"> Minimum 10 Character Required. <
/div> <
/div>
Angular Lifecycle provides the functionality of input data change detection. Angular checks when data-bound properties change, and updates both the view and the component instance as needed.
Angular Components and Directives has same Lifecycle methods. Angular creates, updates, and destroys instances using lifecycle hook methods.
Lifecycle Hook MethodThe ngOnChanges() method runs whenever a parent component loads the child component or parent component change the @Input value of the child component. It runs before the ngOnInit(). If the component has @Input and @Input properties value change then Angular framework calls to the ngOnChanges() method.
This happens frequently, so any operation you perform here impacts performance significantly.
If component has no @Input or you use it without providing any @Input , the framework will not call to the ngOnChanges() method.
ngOnChanges() uses SimpleChanges as an argument.
---SimpleChanges Class---
class SimpleChanges{
constructor(previousValue: any, currentValue: any, firstChange: boolean)
previousValue: any;
currentValue: any;
firstChange: any;
isFirstChane: any;
}
---Child Component TS file---
import { Component, Input, OnInit, OnChanges, SimpleChanges} from '@angular/core';
@Component({
selector: 'app-onchanges',
templateUrl: './onchanges.component.html',
styleUrls: ['./onchanges.component.css']
})
export class OnChangesComponentExample implements OnInit, OnChanges {
@Input() city = 'Mumbai';
oldCity = 'Mumbai';
diff = undefined;
ngOnChanges(changes: SimpleChanges) {
// This will only capture city changes as @Input uses
console.log('Changes Detected. Is first change?', changes.rates.firstChange);
}
}
---Child Component HTML---
City is {{city}}
---Parent Component TS file--- import { Component} from '@angular/core'; @Component({ selector: 'app-parent', templateUrl: './parent.component.html', styleUrls: ['./parent.component.css'] }) export class Parent implements{ cityField = 'Mumbai'; } ---Parent Component HTML--- <
app-onchanges [city]=cityField>app-onchanges> <
input type="text" name="cityField" id="cityField" [(ngModel)]="cityField"/>
The ngOnInit() method called only once after the ngOnChanges() method. The purpose of the ngOnInit() method is to initialize the directive or component after Angular first displays the data-bound properties and sets the directive or component's input properties.
If you required to fetch data on the time of page loading, ngOnInit() is a good place for a component to fetch its initial data.
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-oninit',
templateUrl: './oninit.component.html',
styleUrls: ['./oninit.component.css']
})
export class OnInitComponentExample implements OnInit {
ngOnInit() {
// This method called only once
this.fetchDataFromDatabase();
}
}
The ngDoCheck() is called whenever any change detection occurs. Changes from either @Input or field value. whenever any change occurs, the ngDoCheck() method called immediately after ngOnChanges() and immediately after ngOnInit() on the first time.
The ngOnChanges() method called if we use @Input in the component or directive but ngDoCheck() is called whenever any change detection from either @Input or input field value.
import { Component, DoCheck, Input, OnChanges, SimpleChanges} from '@angular/core';
@Component({
selector: 'app-docheck',
templateUrl: './docheck.component.html',
styleUrls: ['./docheck.component.css']
})
export class DoCheckCityComponent implements DoCheck, OnChanges {
@Input() city = 'Mumbai';
oldCity = 'Mumbai';
diff = undefined;
ngOnChanges(changes: SimpleChanges) {
// This will only capture city changes as @Input uses
console.log('Change detection. Is first change?', changes.rates.firstChange);
}
ngDoCheck() {
// This will capture all changes (@Input or input fields both)
if (this.city !== this.oldCity) {
console.log("changes detected");
}
}
}
The ngAfterContentInit() method runs only one time after the first ngDoCheck() method. This will not be executed after one time execution.
---Child Component TS file---
import { Component, DoCheck, Input, OnChanges, AfterContentInit, SimpleChanges} from '@angular/core';
@Component({
selector: 'app-aftercontentinit',
templateUrl: './aftercontentinit.component.html',
styleUrls: ['./aftercontentinit.component.css']
})
export class AfterContentInitComponent implements DoCheck, OnChanges, AfterContentInit {
@Input() city = 'Mumbai';
oldCity = 'Mumbai';
diff = undefined;
ngOnChanges(changes: SimpleChanges) {
// This will only capture city changes as @Input uses
console.log('Is first change?', changes.rates.firstChange);
}
ngDoCheck() {
// This will capture all changes (@Input or input fields both)
if (this.city !== this.oldCity) {
console.log("changes detected");
}
}
ngAfterContentInit(){
// This method runs once after the first ngDoCheck() method
console.log("after content init");
}
}
The ngAfterContentChecked() method executes every time when ngDoCheck() method called. This executes after ngDoCheck() method and the ngDoCheck() executes whenever any change detection occurs.
Use ngAfterContentChecked whenever you want to call a lifecycle event hook immediately after ngDoCheck.
---Child Component TS file---
import { Component, DoCheck, Input, OnChanges, AfterContentInit, AfterContentChecked , SimpleChanges} from '@angular/core';
@Component({
selector: 'app-aftercontentchecked',
templateUrl: './aftercontentchecked.component.html',
styleUrls: ['./aftercontentchecked.component.css']
})
export class AfterContentCheckedComponent implements DoCheck, OnChanges, AfterContentInit, AfterContentChecked{
@Input() city = 'Mumbai';
oldCity = 'Mumbai';
diff = undefined;
ngOnChanges(changes: SimpleChanges) {
// This will only capture city changes as @Input uses
console.log('Is first change?', changes.rates.firstChange);
}
ngDoCheck() {
// This will capture all changes (@Input or input fields both)
if (this.city !== this.oldCity) {
console.log("changes detected");
}
}
ngAfterContentInit(){
// This method runs once after the first ngDoCheck() method
console.log("after content init");
}
ngAfterContentChecked(){
// This method is called after every subsequent ngDoCheck
console.log("after content checked")
}
}
The ngAfterViewInit() is called one time only after all child components are initialized and checked.
If you want to add functionality of after initialization of all child components and checked then ngAfterViewInit is useful.
---Child Component TS file---
import { Component, Input, AfterViewInit} from '@angular/core';
@Component({
selector: 'app-afterviewinit',
templateUrl: './afterviewinit.component.html',
styleUrls: ['./afterviewinit.component.css']
})
export class AfterViewInitComponent implements AfterViewInit{
@Input() city = 'Mumbai';
oldCity = 'Mumbai';
ngAfterViewInit(){
// This method is called one time only after all child components are initialized and checked.
console.log("after view init")
}
}
The ngAfterViewChecked() is called each time of after execution of the ngAfterContentChecked() method.
If you want to add functionality of after initialization of all child components and checked then ngAfterViewChecked is useful.
---Child Component TS file---
import { Component, AfterViewChecked} from '@angular/core';
@Component({
selector: 'app-afterviewchecked',
templateUrl: './afterviewchecked.component.html',
styleUrls: ['./afterviewchecked.component.css']
})
export class AfterViewCheckedComponent implements AfterViewChecked{
@Input() city = 'Mumbai';
oldCity = 'Mumbai';
ngAfterViewChecked(){
// This method is called each time of after execution of the ngAfterContentChecked method.
console.log("after view Checked")
}
}
The ngOnDestroy() method inside child component or directive is called whenever any child component remove/hide (using ngIf) from the parent component.
The lifecycle will be started again begin from ngOnInit() if you want to show again after removing the child component.
---Child component TS---
import { Component, Input, OnDestroy} from '@angular/core';
@Component({
selector: 'app-ondestroy',
templateUrl: './ondestroy.component.html',
styleUrls: ['./ondestroy.component.css']
})
export class OndestroyComponent implements OnInit, OnDestroy{
@Input() city = 'Mumbai';
ngOnInit() {
// This method called only once
this.fetchDataFromDatabase();
}
ngOnDestroy(){
// This method is called whenever child component remove/hide from parent component.
console.log("On Destroy")
}
}
--Child component HTML---
City is {{city}}
Parent component TS
import { Component} from '@angular/core';
@Component({
selector: 'app-parent',
templateUrl: './appparent.component.html',
styleUrls: ['./appparent.component.scss']
})
export class AppParentComponent implements {
constructor() { }
displayChild = true;
toggleChildComponent(){
this.displayChild = !this.displayChild;
}
}
---Parent component HTML--- <
app-destroy [city]=city *ngIf="displayChild"><
/app-destroy> <
button (click)="toggleChildComponent()">Show/Hide<
/button>
Observable provides the common asynchronous functionality in Angular such as HTTP module uses observables to handle AJAX requests/responses and Router and Forms modules use observables to listen for and respond to user-input events.
---Service TS--- import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http' import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class MessagesService { private AppUrl = 'https://jsonplaceholder.typicode.com/posts'; private LanguageURL = "http://localhost:1111/language"; private StudentURL = "http://localhost:1111/student"; constructor(private http: HttpClient) {} getPostData(): Observable<
String []>{ return this.http.get<
Employee[]>(this.AppUrl); } getLanguage(): Observable<
Array
>{ return this.http.get< Array<
string>>(this.LanguageURL); } getStudents(): Observable<
String []>{ return this.http.get<
String []>(this.StudentURL); } } ---Component TS--- import { Component } from '@angular/core'; import { MessagesService } from './services/messages.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [MessagesService] }) export class AppComponent implements OnInit{ messages: string[] = []; serverData: Employee[] = []; languageData: Array<
string> = []; constructor(private messageService: MessagesService){ this.messages = messageService.getMessage(); } this.messageService.getPostData().subscribe({ next: (response) =>{ this.serverData = response; }, error: (error) => { console.error(error); } }); } getLanguage(){ this.messageService.getLanguage().subscribe({ next: (response) =>{ this.languageData = response; }, error: (error) => { console.error(error); } }); } }
Angular Router service provides functionality of navigation from one view to another view. Need to import RouterModule to use the Router service in your Angular app.
---app-routing.module.ts--- import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './components/home.component'; import { ContactUSComponent } from './components/contactUSComponent.component'; import { ProfileComponent } from './components/profileComponent.component'; import { UserSearchComponent } from './components/userSearchComponent.component'; import { AuthComponent } from './components/AuthComponent.component'; import { RegistrationComponent } from './components/RegistrationComponent.component'; import { LoginComponent } from './components/LoginComponent.component'; import { ChangePasswordComponent } from './components/ChangePasswordComponent.component'; const routes: Routes = [ {path: "", component:HomeComponent}, /*Browser URL - http://localhost:4291/ */ {path: "home", component:HomeComponent}, /*Browser URL - http://localhost:4291/home */ {path: "contactus", component:ContactUSComponent}, /*Browser URL - http://localhost:4291/contactus*/ {path: "profile", component:ProfileComponent}, /* HTML <
a [routerLink]="['profile']">User Details< /a> or < a [routerLink]="['profile']" [queryParams]="{ id:2 }">User Details< /a> Browser URL - http://localhost:4291/profile or http://localhost:4291/profile?id=2 */ {path: "usersearch", component:UserSearchComponent}, /*Browser URL - http://localhost:4291/usersearch */ {path: 'account/:id', component: AccountDetailComponent }, {path: 'account/:id', component: AccountDetailComponent }, /* < a [routerLink]="['/account', 123]">Account 123< /a> Browser URL - http://localhost:4291/account/123 */ {path: "auth", component:AuthComponent, children: [ /*Browser URL - http://localhost:4291/auth */ {path: "registration", component:RegistrationComponent}, /*Browser URL - http://localhost:4291/auth/registration */ {path: "login", component:LoginComponent}, /*Browser URL - http://localhost:4291/auth/login */ {path: "changepassword", component:ChangePasswordComponent} /*Browser URL - http://localhost:4291/auth/changepassword */ } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
---HTML---
Browser URL - http://localhost:4291/
< a [routerLink]="">Dashboard< /a>
-----------------------------------
Browser URL - http://localhost:4291/home
< a [routerLink]="['home']">Home< /a>
-----------------------------------
Browser URL - http://localhost:4291/contactus
< a [routerLink]="['contactus']">Contact< /a>
-----------------------------------
Browser URL - http://localhost:4291/profile
< a [routerLink]="['profile']">Profile< /a>
-----------------------------------
Browser URL - http://localhost:4291/profile?id=2
< a [routerLink]="['profile']" [queryParams]="{ id:2 }">User Details for Id 2< /a>
-----------------------------------
Browser URL - http://localhost:4291/profile?id=3
< a [routerLink]="['profile']" [queryParams]="{ id:3 }">User Details for Id 3< /a>
-----------------------------------
Browser URL - http://localhost:4291/account/123
< a [routerLink]="['/account', 123]">Account 123< /a>
-----------------------------------
Browser URL - http://localhost:4291/account/150
< a [routerLink]="['/account', 150]">Account 150< /a>
---If want to navigate from TS file---
Browser URL - http://localhost:4291/home
this.router.navigate(
['/home']
);
or this.router.navigateByUrl('home');
-------------------------------
Browser URL - http://localhost:4291/profile
this.router.navigate(
['/profile']
);
or this.router.navigateByUrl('profile');
-------------------------------
Browser URL - http://localhost:4291/profile?id=2
this.router.navigate(
['/profile'],
{ queryParams: { id: 2'} }
);
or this.router.navigateByUrl('profile?id=2');
-------------------------------
Browser URL - http://localhost:4291/'profile?id=3
this.router.navigate(
['/profile'],
{ queryParams: { id: 3'} }
);
or this.router.navigateByUrl('profile?id=3');
-------------------------------
Browser URL - http://localhost:4291/account/3
this.router.navigate(
['/account','3'],
);
or this.router.navigateByUrl('account/3');