1.
Introduction to Angular
● Angular is a TypeScript-based open-source front-end web application framework
developed by Google.
● It’s used to build single-page applications (SPAs).
● Features include two-way data binding, dependency injection, routing, and
component-based architecture.
2. Setting Up the Environment with Angular CLI
Prerequisites:
● Install Node.js (includes npm): https://nodejs.org/
● Install Angular CLI globally using npm:
npm install -g @angular/cli
3. Project Setup
● Create a new Angular project:
ng new my-app
● Choose routing (optional) and stylesheet format (e.g., CSS, SCSS).
Navigate into the project:
cd my-app
Serve the app locally:
ng serve
Open in browser: http://localhost:4200
4. Bootstrapping the App
● Entry point: main.ts
platformBrowserDynamic().bootstrapModule(AppModule);
● Root module: app.module.ts
○ Declares components and imports modules.
● Root component: app.component.ts
○ Selector: <app-root> (used in index.html)
○ HTML: app.component.html is rendered on the page.
5. Building Components
● Generate a component:
bash
CopyEdit
ng generate component component-name
○ Or shorthand: ng g c component-name
● A component includes:
○ .ts: TypeScript logic
○ .html: template
○ .css/.scss: styles
○ .spec.ts: for unit testing
Example:
@Component({
selector: 'app-hello',
templateUrl: './hello.component.html',
styleUrls: ['./hello.component.css']
})
export class HelloComponent {
message = 'Hello, Angular!';
}
6. Understanding App Structure
Typical Angular app folder structure:
src/
├── app/
│ ├── app.component.ts/html/css
│ ├── app.module.ts
│ └── [other components, services, modules]
├── assets/
├── environments/
├── index.html
├── main.ts
└── styles.css
● app/: All core logic resides here (components, modules,
services).
● assets/: Static files like images or JSON data.
● environments/: Environment-specific configs (e.g., dev vs prod).
● angular.json: Angular CLI config.
● package.json: Dependencies and scripts.
1. Creating and Nesting Components
✅ Create a Component:
ng generate component child
# OR
ng g c child
✅ Nesting Components:
Use the child component selector in the parent’s template:
<!-- app.component.html -->
<h1>Parent Component</h1>
<app-child></app-child>
2. Setting Up Templates
You can define templates in:
● HTML File (external):
templateUrl: './child.component.html'
Inline (inline template):
template: `<p>This is an inline template</p>`
Templates can use Angular directives like:
<ul>
<li *ngFor="let item of items">{{ item }}</li>
</ul>
🔹 3. Data Binding Overview
Angular supports 4 types of data binding:
Type Syntax Description
Interpolation {{ data }} Display data in the template
Property [property]="da Bind data from TS to HTML
Binding ta" property
Event Binding (event)="handl Respond to user actions
er"
Two-Way [(ngModel)]="d Sync data both ways (requires
Binding ata" FormsModule)
🔹 4. Two-Way Data Binding
✅ Setup:
1.Import FormsModule in app.module.ts:
import { FormsModule } from '@angular/forms';
@NgModule({
imports: [FormsModule]
})
2. In component template:
<input [(ngModel)]="username" />
<p>Hello, {{ username }}!</p>
5. Managing @Input and @Output (Parent-Child
Communication)
✅ @Input: Pass data from parent → child
Parent: (html)
<app-child [childMessage]="messageFromParent"></app-child>
Child:(ts)
@Input() childMessage: string;
html:
<p>Child says: {{ childMessage }}</p>
@Output: Emit event from child → parent
Child:ts
@Output() messageEvent = new EventEmitter<string>();
sendMessage() {
this.messageEvent.emit('Hello from Child!');
}
Html:
<button (click)="sendMessage()">Send to Parent</button>
Parent:html
<app-child (messageEvent)="receiveMessage($event)"></app-child>
<p>Received: {{ message }}</p>
Ts:
receiveMessage(msg: string) {
this.message = msg;
}
✅ Summary
Feature Purpose
@Input() Pass data to child component
@Output() Send data/event to parent
component
[(ngModel Two-way binding between input &
)] variable
[property One-way binding from TS to DOM
]
(event) One-way binding from DOM to TS
1. Built-in Directives in Angular
✅ Structural Directives
Change the structure of the DOM.
● *ngIf – Conditionally includes a template.
<p *ngIf="isVisible">Now you see me</p>
*ngFor – Loops through items.
<li *ngFor="let user of users">{{ user }}</li>
*ngSwitch – Conditional branching.
<div [ngSwitch]="role">
<p *ngSwitchCase="'admin'">Admin</p>
<p *ngSwitchDefault>User</p>
</div>
✅ Attribute Directives
Change the appearance or behavior of an element.
● ngClass, ngStyle, [class.className], [style.property]
<div [ngClass]="{'active': isActive}"></div>
<p [style.color]="isError ? 'red' : 'green'">Styled text</p>
2. Creating Custom Attribute Directives
✅ Step 1: Generate a directive
ng generate directive highlight
✅ Step 2: Use Renderer2 and HostListener
highlight.directive.ts
import { Directive, ElementRef, Renderer2, HostListener } from
'@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(private el: ElementRef, private renderer: Renderer2) {}
@HostListener('mouseenter') onMouseEnter() {
this.renderer.setStyle(this.el.nativeElement, 'backgroundColor',
'yellow');
}
@HostListener('mouseleave') onMouseLeave() {
this.renderer.removeStyle(this.el.nativeElement,
'backgroundColor');
}
}
✅ Step 3: Use in template
<p appHighlight>Hover me!</p>
🔹 3. Applying Styles
✅ Inline styles
<p style="color: blue;">Styled with inline CSS</p>
✅ Component styles (.component.css)
p {
font-weight: bold;
color: green;
}
✅ Dynamic styles
<p [ngStyle]="{ 'color': dynamicColor }">Styled dynamically</p>
🔹 4. View Encapsulation
Angular applies style scoping using View Encapsulation. You can
control it via the encapsulation property.
ts:
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css'],
encapsulation: ViewEncapsulation.None // or Emulated / ShadowDom
})
Mode Description
Emulated Scoped styles with attribute selectors
(default)
None Global styles (no encapsulation)
ShadowDom Uses native shadow DOM (limited
browser support)
🔹 5. Bootstrap Integration
✅ Install Bootstrap
npm install bootstrap
✅ Add to angular.json
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"src/styles.css"
],
"scripts": [
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
]
✅ Use Bootstrap classes
<div class="container mt-4">
<button class="btn btn-primary">Bootstrap Button</button>
</div>
✅ Summary
Feature Purpose
*ngIf, *ngFor, Control DOM rendering
ngSwitch
ngClass, ngStyle Dynamic styling
Custom Directives Encapsulate reusable behavior
via attributes
Renderer2, Safely interact with the DOM
HostListener
View Encapsulation Style isolation and scoping
Bootstrap Prebuilt styles and responsive
layout
1. Template-driven vs Reactive Forms
✅ Template-driven Forms (simpler, for small apps)
● Defined in HTML template.
● Requires importing FormsModule.
Example:
// app.module.ts
import { FormsModule } from '@angular/forms';
@NgModule({ imports: [FormsModule] })
<form #form="ngForm" (ngSubmit)="submit(form)">
<input name="username" ngModel required />
</form>
✅ Reactive Forms (more scalable and robust)
● Form model is defined in TypeScript.
● Requires ReactiveFormsModule.
Example:
// app.module.ts
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({ imports: [ReactiveFormsModule] })
form = new FormGroup({
username: new FormControl('', [Validators.required,
Validators.minLength(3)])
});
<form [formGroup]="form" (ngSubmit)="submit()">
<input formControlName="username" />
</form>
🔹 2. Validators (Built-in and Custom)
✅ Built-in Validators:
● Validators.required
● Validators.minLength
● Validators.email
✅ Custom Validator Example:
function forbiddenNameValidator(control: AbstractControl):
ValidationErrors | null {
const forbidden = /admin/.test(control.value);
return forbidden ? { forbiddenName: { value: control.value } } :
null;
}
🔹 3. Creating and Using Services with
Dependency Injection
✅ Create a Service:
ng generate service data
✅ Basic Service Example:
@Injectable({ providedIn: 'root' })
export class DataService {
getData() {
return ['Angular', 'React', 'Vue'];
}
}
✅ Injecting a Service into a Component:
constructor(private dataService: DataService) {}
ngOnInit() {
this.frameworks = this.dataService.getData();
}
4. Dependency Injection (DI)
● Angular uses a hierarchical injector system.
● Decorate classes with @Injectable() to make them injectable.
● Services can be:
○ Provided in root (singleton across app)
○ Scoped to a component or module
🔹 5. Pipes
✅ Built-in Pipes:
● date, uppercase, lowercase, currency, percent, json, etc.
Example:
<p>{{ today | date:'shortDate' }}</p>
<p>{{ price | currency:'USD' }}</p>
✅ Custom Pipe:
generate with CLI:
ng generate pipe capitalize
capitalize.pipe.ts
@Pipe({ name: 'capitalize' })
export class CapitalizePipe implements PipeTransform {
transform(value: string): string {
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
Usage in template:
<p>{{ 'hello' | capitalize }}</p> <!-- Output: Hello -->
✅ Summary Table
Feature Template-dri Reactive
ven
Form In template In TypeScript
setup
Validato HTML-based Code-based
rs
Flexibil Simple Complex,
ity scalable
🔹 1. Routing and Navigation
✅ Setup
Enable routing when generating your Angular app or manually in
app-routing.module.ts.
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'users/:id', component: UserDetailComponent },
{ path: 'admin', component: AdminComponent, canActivate: [AuthGuard]
},
{ path: '**', component: NotFoundComponent } // wildcard route
];
Import and configure:
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
✅ Navigation
Use the routerLink directive:
<a routerLink="/users/5">User 5</a>
Or navigate programmatically:
this.router.navigate(['/users', userId]);
✅ Child Routes
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
children: [
{ path: 'stats', component: StatsComponent },
{ path: 'settings', component: SettingsComponent }
]
}
];
Use <router-outlet></router-outlet> inside DashboardComponent.
✅ Route Parameters
In the component:
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.paramMap.subscribe(params => {
const id = params.get('id');
});
}
🔹 2. HTTP Requests with Observables
✅ Setup HttpClient
Import in app.module.ts:
import { HttpClientModule } from '@angular/common/http';
@NgModule({ imports: [HttpClientModule] })
✅ Example Service
@Injectable({ providedIn: 'root' })
export class UserService {
constructor(private http: HttpClient) {}
getUsers(): Observable<User[]> {
return this.http.get<User[]>('/api/users');
}
getUser(id: number): Observable<User> {
return this.http.get<User>(`/api/users/${id}`);
}
}
✅ In Component
ngOnInit() {
this.userService.getUsers().subscribe(users => this.users = users);
}
3. JWT Authentication & Route Guards
✅ Login Flow Example
● On successful login, backend returns a JWT.
● Store the token (e.g., in localStorage).
● Add the token to HTTP requests using an interceptor.
✅ Auth Interceptor
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
const token = localStorage.getItem('token');
if (token) {
const cloned = req.clone({
headers: req.headers.set('Authorization', `Bearer ${token}`)
});
return next.handle(cloned);
}
return next.handle(req);
}
}
Provide in module:
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true
}
]
✅ Auth Guard to Protect Routes
ts
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router:
Router) {}
canActivate(): boolean {
if (this.authService.isAuthenticated()) {
return true;
}
this.router.navigate(['/login']);
return false;
}
}
✅ Route Guard in Routing
{ path: 'admin', component: AdminComponent, canActivate: [AuthGuard] }
✅ Summary Table
Feature Purpose
routerLink, Navigate between components/pages
navigate()
Route parameters Pass dynamic data via URLs
HttpClientModule Make GET/POST/PUT/DELETE calls to backend
Observable Handle async data streams from HTTP calls
JWT Secure APIs, store token, use with
Authentication Authorization header
Interceptor Automatically attach token to HTTP
requests
Route Guard Restrict access to routes based on auth
1. Lazy Loading Modules
Lazy loading loads feature modules only when needed, reducing initial
load time.
✅ Step 1: Create a Feature Module with Routing
ng generate module features/admin --route admin --module app.module
This automatically sets up lazy loading in your app-routing.module.ts:
const routes: Routes = [
{ path: 'admin', loadChildren: () =>
import('./features/admin/admin.module').then(m => m.AdminModule) }
];
const routes: Routes = [
{ path: 'admin', loadChildren: () =>
import('./features/admin/admin.module').then(m => m.AdminModule) }
];
📌 Angular uses dynamic import() for lazy-loaded modules.
🔹 2. Preloading Strategies
Preloading loads modules after the initial app load to make them ready
in the background.
✅ Use Built-in Strategies
In app-routing.module.ts:
import { PreloadAllModules } from '@angular/router';
@NgModule({
imports: [RouterModule.forRoot(routes, { preloadingStrategy:
PreloadAllModules })]
})
✅ Custom Preloading Strategy
Create a service:
@Injectable({ providedIn: 'root' })
export class CustomPreloadingStrategy implements PreloadingStrategy {
preload(route: Route, load: () => Observable<any>): Observable<any>
{
return route.data && route.data['preload'] ? load() : of(null);
}
}
Use in routes:
{ path: 'admin', loadChildren: () =>
import('./admin/admin.module').then(m => m.AdminModule), data: {
preload: true } }
In app-routing.module.ts:
RouterModule.forRoot(routes, { preloadingStrategy:
CustomPreloadingStrategy })
🔹 3. Advanced Route Guards
Angular supports four types of route guards:
Guard Type Purpose
CanActivate Controls access before route
activates
CanDeactivate Checks before navigating away from
component
CanActivateCh Controls access to child routes
ild
Resolve Preloads data before route loads
✅ CanDeactivate Example
Create a component interface:
export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> |
boolean;
}
Guard:
@Injectable({ providedIn: 'root' })
export class ConfirmDeactivateGuard implements
CanDeactivate<CanComponentDeactivate> {
canDeactivate(component: CanComponentDeactivate) {
return component.canDeactivate ? component.canDeactivate() : true;
}
}
Component:
canDeactivate(): boolean {
return confirm('Unsaved changes. Leave page?');
}
Route:
{ path: 'edit', component: EditComponent, canDeactivate:
[ConfirmDeactivateGuard] }
✅ Resolve Guard Example
To load data before activating a route:
Guard:
@Injectable({ providedIn: 'root' })
export class UserResolver implements Resolve<User> {
constructor(private userService: UserService) {}
resolve(route: ActivatedRouteSnapshot): Observable<User> {
return this.userService.getUser(route.paramMap.get('id'));
}
}
Route:
{ path: 'user/:id', component: UserComponent, resolve: { user:
UserResolver } }
Component:
ngOnInit() {
this.route.data.subscribe(data => this.user = data['user']);
}
✅ Summary
Feature Description
Lazy Loading Loads modules only when needed, improves
initial load time
Preloading Loads lazy modules in background for faster
access
CanActivate Prevents access to route unless condition is
met
CanDeactivate Warns users before leaving (e.g., unsaved
form)
Resolve Loads data before route activation
CanActivateChi Protects child routes under a parent route
ld