0% found this document useful (0 votes)
19 views31 pages

Angular Complete Notes

This document is a comprehensive guide to Angular, covering its features, setup, components, templates, directives, modules, dependency injection, routing, forms, and HTTP client. It provides detailed explanations, code examples, and best practices for each topic, making it suitable for beginners to advanced users. The content is structured in parts, starting from an introduction to Angular and progressing through various essential concepts and functionalities.

Uploaded by

ashok.it1259
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views31 pages

Angular Complete Notes

This document is a comprehensive guide to Angular, covering its features, setup, components, templates, directives, modules, dependency injection, routing, forms, and HTTP client. It provides detailed explanations, code examples, and best practices for each topic, making it suitable for beginners to advanced users. The content is structured in parts, starting from an introduction to Angular and progressing through various essential concepts and functionalities.

Uploaded by

ashok.it1259
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Angular

Complete Notes: Beginner to Advanced


Covers Angular 17+ | TypeScript | RxJS | NgRx | Testing
Part 1: Introduction to Angular
1.1 What is Angular?
Angular is a platform and framework for building single-page client applications using HTML,
CSS, and TypeScript. It is developed and maintained by Google and is one of the most popular
frontend frameworks in the world.

Key Features
• Component-based architecture
• Two-way data binding
• Dependency Injection (DI)
• TypeScript-first approach
• Powerful CLI tooling
• Built-in routing, forms, HTTP client
• RxJS for reactive programming

1.2 Angular vs AngularJS


Feature AngularJS (1.x) Angular (2+)
Language JavaScript TypeScript
Architecture MVC Component-based
Mobile Support Limited Yes (Ionic)
Performance Slower Faster
CLI No Yes (Angular CLI)

1.3 Setting Up Angular


Prerequisites
• [Link] (v18+) and npm
• Angular CLI
• Code editor (VS Code recommended)

Installation
# Install Angular CLI globally
npm install -g @angular/cli
# Create a new project
ng new my-app

# Navigate to project
cd my-app

# Serve the app


ng serve

Project Structure
my-app/
├── src/
│ ├── app/
│ │ ├── [Link] ← Root component
│ │ ├── [Link] ← Template
│ │ ├── [Link] ← Styles
│ │ └── [Link] ← Root module
│ ├── assets/ ← Static files
│ ├── environments/ ← Env configs
│ └── [Link] ← Entry point
├── [Link] ← CLI config
├── [Link]
└── [Link]
Part 2: Components
2.1 What is a Component?
A component is the basic building block of an Angular application. Each component controls a
patch of screen called a view. Components consist of three parts: a TypeScript class, an HTML
template, and optional CSS styles.

2.2 Creating a Component


Using CLI (recommended)
ng generate component my-component
# or shorthand:
ng g c my-component

Component Anatomy
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-my-component', // HTML tag name
templateUrl: './[Link]', // External template
styleUrls: ['./[Link]'] // Styles
// OR inline:
// template: `<h1>Hello</h1>`,
// styles: [`h1 { color: blue; }`]
})
export class MyComponent implements OnInit {
title: string = 'Hello Angular';
count: number = 0;

constructor() { }

ngOnInit(): void {
// Runs once on component load
}

increment(): void {
[Link]++;
}
}
2.3 Data Binding
Interpolation (Component → Template)
// Component
name = 'Angular';

// Template
<h1>Hello {{ name }}</h1>
<p>2 + 2 = {{ 2 + 2 }}</p>

Property Binding
// Component
imageUrl = '[Link]
isDisabled = true;

// Template
<img [src]="imageUrl">
<button [disabled]="isDisabled">Click</button>

Event Binding
// Component
onClick() { [Link]('Clicked!'); }

// Template
<button (click)="onClick()">Click me</button>
<input (keyup)="onKeyUp($event)">

Two-Way Binding (ngModel)


// Import FormsModule in [Link]

// Component
username = '';

// Template
<input [(ngModel)]="username">
<p>Hello, {{ username }}</p>

Note: Two-way binding uses the 'banana in a box' syntax: [( )] = property binding + event binding
combined.
2.4 Component Communication
Parent to Child — @Input()
// Child component
import { Input } from '@angular/core';

@Component({ selector: 'app-child', ... })


export class ChildComponent {
@Input() title: string = '';
@Input() count: number = 0;
}

// Parent template
<app-child [title]="'Hello'" [count]="myCount"></app-child>

Child to Parent — @Output() & EventEmitter


// Child component
import { Output, EventEmitter } from '@angular/core';

export class ChildComponent {


@Output() messageSent = new EventEmitter<string>();

sendMessage() {
[Link]('Hello from child!');
}
}

// Parent template
<app-child (messageSent)="onMessage($event)"></app-child>

// Parent component
onMessage(msg: string) { [Link](msg); }

2.5 Component Lifecycle Hooks


Hook When it runs
ngOnChanges() When @Input() values change
ngOnInit() Once, after first ngOnChanges (use for setup)
ngDoCheck() Every change detection cycle
ngAfterContentInit() After ng-content is projected
ngAfterViewInit() After component view is initialized
ngOnDestroy() Just before component is destroyed (cleanup)
Part 3: Templates & Directives
3.1 Built-in Structural Directives
*ngIf
<div *ngIf="isLoggedIn">Welcome back!</div>
<div *ngIf="isLoggedIn; else loginBlock">Welcome!</div>

<ng-template #loginBlock>
<p>Please log in.</p>
</ng-template>

*ngFor
// Component
users = ['Alice', 'Bob', 'Charlie'];

// Template
<ul>
<li *ngFor="let user of users; let i = index">
{{ i + 1 }}. {{ user }}
</li>
</ul>

// With trackBy for performance


<li *ngFor="let item of items; trackBy: trackById">

// Component
trackById(index: number, item: any) { return [Link]; }

*ngSwitch
<div [ngSwitch]="color">
<p *ngSwitchCase="'red'">Red selected</p>
<p *ngSwitchCase="'blue'">Blue selected</p>
<p *ngSwitchDefault>Unknown color</p>
</div>

3.2 Built-in Attribute Directives


ngClass
<div [ngClass]="{'active': isActive, 'error': hasError}">
// Or with array:
<div [ngClass]="['class1', 'class2']">
// Or with string:
<div [ngClass]="className">

ngStyle
<div [ngStyle]="{'color': textColor, 'font-size': fontSize + 'px'}">
Styled text
</div>

3.3 Custom Directives


// ng g d highlight

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({ selector: '[appHighlight]' })


export class HighlightDirective {
@Input() appHighlight = 'yellow';

constructor(private el: ElementRef) {}

@HostListener('mouseenter')
onMouseEnter() {
[Link] = [Link];
}

@HostListener('mouseleave')
onMouseLeave() {
[Link] = '';
}
}

// Usage:
<p appHighlight="lightblue">Hover over me</p>

3.4 Pipes
Built-in Pipes
{{ name | uppercase }} → ANGULAR
{{ name | lowercase }} → angular
{{ price | currency:'INR' }} → ₹1,000.00
{{ date | date:'dd/MM/yyyy' }} → 18/03/2026
{{ ratio | percent }} → 75%
{{ object | json }} → { 'key': 'value' }
{{ 'hello world' | titlecase }} → Hello World
{{ items | sli[Link] }} → first 3 items

Custom Pipe
// ng g p truncate

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'truncate' })


export class TruncatePipe implements PipeTransform {
transform(value: string, limit: number = 50): string {
return [Link] > limit ? [Link](0, limit) + '...' : value;
}
}

// Usage:
<p>{{ longText | truncate:100 }}</p>
Part 4: Modules & Dependency Injection
4.1 NgModules
NgModules organize an application into cohesive blocks of functionality. Every Angular app has
at least one module — the root module (AppModule).
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './[Link]';
import { AppComponent } from './[Link]';

@NgModule({
declarations: [ // Components, directives, pipes belonging to this module
AppComponent
],
imports: [ // Other modules this module needs
BrowserModule,
AppRoutingModule
],
providers: [], // Services available to this module
bootstrap: [AppComponent] // Root component to launch
})
export class AppModule { }

4.2 Services & Dependency Injection


Services are classes that handle business logic, data access, or shared functionality. Angular's
DI system provides services to components automatically.
// ng g s user

import { Injectable } from '@angular/core';

@Injectable({
providedIn: 'root' // Singleton — available app-wide
})
export class UserService {
private users: string[] = ['Alice', 'Bob'];

getUsers(): string[] {
return [Link];
}

addUser(name: string): void {


[Link](name);
}
}

// Injecting into a component


export class AppComponent {
users: string[];

constructor(private userService: UserService) {


[Link] = [Link]();
}
}

Best Practice: Always use providedIn: 'root' for services you want as app-wide singletons. This also
enables tree-shaking.
Part 5: Routing & Navigation
5.1 Setting Up Routing
// [Link]
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/[Link]';
import { AboutComponent } from './about/[Link]';
import { NotFoundComponent } from './not-found/[Link]';

const routes: Routes = [


{ path: '', component: HomeComponent }, // Default
{ path: 'about', component: AboutComponent },
{ path: '**', component: NotFoundComponent } // Wildcard (must be last)
];

@NgModule({
imports: [[Link](routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

Router Outlet & Navigation Links


<!-- [Link] -->
<nav>
<a routerLink="/">Home</a>
<a routerLink="/about" routerLinkActive="active">About</a>
</nav>

<router-outlet></router-outlet> <!-- Views render here -->

5.2 Route Parameters


// Routes config
{ path: 'user/:id', component: UserDetailComponent }

// Component — reading the param


import { ActivatedRoute } from '@angular/router';

export class UserDetailComponent implements OnInit {


userId!: string;

constructor(private route: ActivatedRoute) {}


ngOnInit() {
[Link] = [Link]('id')!;
// Or subscribe for dynamic updates:
[Link](params => {
[Link] = [Link]('id')!;
});
}
}

5.3 Programmatic Navigation


import { Router } from '@angular/router';

export class LoginComponent {


constructor(private router: Router) {}

onLogin() {
// Navigate after login
[Link](['/dashboard']);
// With query params:
[Link](['/search'], { queryParams: { q: 'angular' } });
}
}

5.4 Route Guards


// ng g guard auth

import { Injectable } from '@angular/core';


import { CanActivate, Router } from '@angular/router';

@Injectable({ providedIn: 'root' })


export class AuthGuard implements CanActivate {
constructor(private router: Router) {}

canActivate(): boolean {
const isLoggedIn = !![Link]('token');
if (!isLoggedIn) [Link](['/login']);
return isLoggedIn;
}
}

// Apply in routes:
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }
5.5 Lazy Loading
// Lazy load a feature module
const routes: Routes = [
{
path: 'admin',
loadChildren: () =>
import('./admin/[Link]').then(m => [Link])
}
];

// Benefits: smaller initial bundle, faster first load


Part 6: Forms
6.1 Template-Driven Forms
Simple forms built using directives in the template. Best for simple use cases.
// Import in module:
import { FormsModule } from '@angular/forms';

// Template
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm)">
<input
name="email"
[(ngModel)]="email"
required email
#emailField="ngModel"
/>
<div *ngIf="[Link] && [Link]">
Invalid email
</div>
<button type="submit" [disabled]="[Link]">Submit</button>
</form>

// Component
email = '';
onSubmit(form: NgForm) {
[Link]([Link]);
}

6.2 Reactive Forms


More robust forms built in the component class. Best for complex forms, dynamic fields, and
custom validation.
// Import in module:
import { ReactiveFormsModule } from '@angular/forms';

// Component
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

export class LoginComponent {


loginForm: FormGroup;

constructor(private fb: FormBuilder) {


[Link] = [Link]({
email: ['', [[Link], [Link]]],
password: ['', [[Link], [Link](6)]]
});
}

get email() { return [Link]('email'); }

onSubmit() {
if ([Link]) {
[Link]([Link]);
}
}
}

// Template
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<input formControlName="email" />
<div *ngIf="email?.invalid && email?.touched">
<span *ngIf="email?.errors?.['required']">Email required</span>
<span *ngIf="email?.errors?.['email']">Invalid email</span>
</div>
<input type="password" formControlName="password" />
<button type="submit" [disabled]="[Link]">Login</button>
</form>

6.3 Custom Validators


import { AbstractControl, ValidatorFn } from '@angular/forms';

export function noSpaceValidator(): ValidatorFn {


return (control: AbstractControl) => {
return [Link]?.includes(' ')
? { noSpace: true }
: null;
};
}

// Usage:
username: ['', [[Link], noSpaceValidator()]]
Part 7: HTTP Client & APIs
7.1 Setting Up HttpClient
// [Link]
import { HttpClientModule } from '@angular/common/http';

@NgModule({
imports: [HttpClientModule]
})

7.2 Making HTTP Requests


import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

interface Post {
id: number;
title: string;
body: string;
}

@Injectable({ providedIn: 'root' })


export class PostService {
private apiUrl = '[Link]

constructor(private http: HttpClient) {}

getPosts(): Observable<Post[]> {
return [Link]<Post[]>([Link]);
}

getPost(id: number): Observable<Post> {


return [Link]<Post>(`${[Link]}/${id}`);
}

createPost(post: Partial<Post>): Observable<Post> {


return [Link]<Post>([Link], post);
}

updatePost(id: number, post: Partial<Post>): Observable<Post> {


return [Link]<Post>(`${[Link]}/${id}`, post);
}
deletePost(id: number): Observable<void> {
return [Link]<void>(`${[Link]}/${id}`);
}
}

// In component:
ngOnInit() {
[Link]().subscribe({
next: (posts) => [Link] = posts,
error: (err) => [Link](err),
complete: () => [Link]('Done')
});
}

7.3 HTTP Interceptors


import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
const token = [Link]('token');
const cloned = [Link]({
headers: [Link]('Authorization', `Bearer ${token}`)
});
return [Link](cloned);
}
}

// Register in AppModule providers:


{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
Part 8: RxJS & Reactive Programming
8.1 What is RxJS?
RxJS (Reactive Extensions for JavaScript) is a library for composing asynchronous and event-
based programs using Observables. Angular uses it extensively for HTTP, forms, and routing.

8.2 Key Concepts


• Observable — a stream of data over time
• Observer — consumes the data (next, error, complete)
• Subscription — the connection between Observable and Observer
• Operators — transform, filter, combine streams
• Subject — both Observable and Observer

8.3 Common RxJS Operators


import { of, from, interval, Subject } from 'rxjs';
import { map, filter, mergeMap, switchMap,
catchError, debounceTime, distinctUntilChanged,
takeUntil, tap, forkJoin } from 'rxjs/operators';

// map — transform each value


of(1, 2, 3).pipe(
map(x => x * 10)
).subscribe([Link]); // 10, 20, 30

// filter — only emit matching values


of(1, 2, 3, 4).pipe(
filter(x => x % 2 === 0)
).subscribe([Link]); // 2, 4

// switchMap — cancel previous, use latest (great for search)


searchTerm$.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap(term => [Link](`/search?q=${term}`))
).subscribe(results => [Link] = results);

// forkJoin — combine multiple observables (like [Link])


forkJoin([
[Link]('/users'),
[Link]('/products')
]).subscribe(([users, products]) => { ... });

// catchError — handle errors


[Link]('/api/data').pipe(
catchError(err => of([])) // Return fallback on error
).subscribe(data => [Link] = data);

8.4 Subject & BehaviorSubject


import { Subject, BehaviorSubject } from 'rxjs';

// Subject — no initial value


const subject = new Subject<string>();
[Link](val => [Link]('A:', val));
[Link]('hello'); // A: hello

// BehaviorSubject — has initial value, emits to new subscribers


const counter = new BehaviorSubject<number>(0);
[Link](val => [Link](val)); // 0 immediately
[Link](1); // 1
[Link]([Link]()); // 1

// Typical use — shared state service


@Injectable({ providedIn: 'root' })
export class CartService {
private cartCount = new BehaviorSubject<number>(0);
cartCount$ = [Link]();

updateCount(n: number) {
[Link](n);
}
}

8.5 Async Pipe


// Component — no manual subscribe/unsubscribe needed
export class PostsComponent {
posts$ = [Link]();
constructor(private postService: PostService) {}
}

// Template
<div *ngIf="posts$ | async as posts">
<div *ngFor="let post of posts">
{{ [Link] }}
</div>
</div>

Best Practice: Use the async pipe in templates instead of subscribing manually — it handles
unsubscription automatically, preventing memory leaks.
Part 9: Advanced Angular
9.1 Change Detection
Angular checks the whole component tree by default (Default strategy). For performance-critical
apps, use OnPush to only check when @Input references change.
import { ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';

@Component({
selector: 'app-card',
changeDetection: [Link]
})
export class CardComponent {
@Input() data!: any;

constructor(private cdr: ChangeDetectorRef) {}

// Manually trigger detection if needed


refresh() { [Link](); }
}

9.2 Content Projection (ng-content)


// Card component template
<div class="card">
<div class="card-header">
<ng-content select="[card-title]"></ng-content>
</div>
<div class="card-body">
<ng-content></ng-content>
</div>
</div>

// Usage
<app-card>
<h2 card-title>My Title</h2>
<p>Card body content</p>
</app-card>

9.3 ViewChild & ContentChild


import { ViewChild, ElementRef, AfterViewInit } from '@angular/core';

export class AppComponent implements AfterViewInit {


@ViewChild('myInput') inputRef!: ElementRef;
@ViewChild(ChildComponent) child!: ChildComponent;

ngAfterViewInit() {
[Link]();
[Link]();
}
}

// Template
<input #myInput placeholder="Focus me" />

9.4 Standalone Components (Angular 14+)


Standalone components don't need NgModules. This simplifies app architecture and is the
recommended approach in Angular 17+.
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';

@Component({
selector: 'app-home',
standalone: true,
imports: [CommonModule, RouterModule], // Import directly!
template: `<h1>Home Page</h1>`
})
export class HomeComponent { }

// [Link] — bootstrap standalone app


import { bootstrapApplication } from '@angular/platform-browser';
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes)]
});

9.5 Signals (Angular 16+)


Signals are a new reactive primitive in Angular that provide fine-grained reactivity and simpler
change detection.
import { signal, computed, effect } from '@angular/core';

export class CounterComponent {


count = signal(0); // Writable signal
doubled = computed(() => [Link]() * 2); // Derived signal

constructor() {
effect(() => { // Side effect
[Link]('Count changed:', [Link]());
});
}

increment() { [Link](v => v + 1); }


reset() { [Link](0); }
}

// Template
<p>Count: {{ count() }}</p>
<p>Doubled: {{ doubled() }}</p>
<button (click)="increment()">+</button>
Part 10: State Management with NgRx
10.1 NgRx Core Concepts
• Store — single source of truth (immutable state)
• Actions — events describing what happened
• Reducers — pure functions that update state
• Selectors — queries to extract data from state
• Effects — handle async side effects (HTTP calls)

npm install @ngrx/store @ngrx/effects @ngrx/entity

10.2 NgRx Example — Counter


// actions/[Link]
import { createAction } from '@ngrx/store';

export const increment = createAction('[Counter] Increment');


export const decrement = createAction('[Counter] Decrement');
export const reset = createAction('[Counter] Reset');

// reducers/[Link]
import { createReducer, on } from '@ngrx/store';

export const initialState = { count: 0 };

export const counterReducer = createReducer(


initialState,
on(increment, state => ({ ...state, count: [Link] + 1 })),
on(decrement, state => ({ ...state, count: [Link] - 1 })),
on(reset, state => ({ ...state, count: 0 }))
);

// selectors/[Link]
import { createSelector, createFeatureSelector } from '@ngrx/store';

export const selectCounterFeature = createFeatureSelector('counter');


export const selectCount = createSelector(
selectCounterFeature,
state => [Link]
);

// In component
export class CounterComponent {
count$ = [Link](selectCount);

constructor(private store: Store) {}

increment() { [Link](increment()); }
decrement() { [Link](decrement()); }
}
Part 11: Testing in Angular
11.1 Unit Testing with Jasmine & Karma
// [Link]
import { TestBed } from '@angular/core/testing';
import { CounterService } from './[Link]';

describe('CounterService', () => {
let service: CounterService;

beforeEach(() => {
[Link]({});
service = [Link](CounterService);
});

it('should be created', () => {


expect(service).toBeTruthy();
});

it('should increment count', () => {


[Link]();
expect([Link]()).toBe(1);
});
});

11.2 Component Testing


import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppComponent } from './[Link]';

describe('AppComponent', () => {
let fixture: ComponentFixture<AppComponent>;
let component: AppComponent;

beforeEach(async () => {
await [Link]({
declarations: [AppComponent]
}).compileComponents();

fixture = [Link](AppComponent);
component = [Link];
[Link]();
});
it('should render title', () => {
const compiled = [Link] as HTMLElement;
expect([Link]('h1')?.textContent).toContain('Hello');
});
});

// Run tests:
ng test
Part 12: Performance & Best Practices
12.1 Performance Tips
• Use OnPush change detection for components with immutable inputs
• Use trackBy with *ngFor to avoid re-rendering entire lists
• Lazy load feature modules to reduce initial bundle size
• Use the async pipe instead of manual subscriptions
• Unsubscribe from Observables in ngOnDestroy to prevent memory leaks
• Use pure pipes instead of methods in templates
• Avoid complex expressions in templates

12.2 Unsubscription Patterns


// Pattern 1: takeUntil (recommended)
export class MyComponent implements OnDestroy {
private destroy$ = new Subject<void>();

ngOnInit() {
[Link]$.pipe(
takeUntil([Link]$)
).subscribe(data => [Link] = data);
}

ngOnDestroy() {
[Link]$.next();
[Link]$.complete();
}
}

12.3 Angular CLI Useful Commands


Command Description
ng new app-name Create new project
ng serve Run dev server
ng build --prod Build for production
ng g c component-name Generate component
ng g s service-name Generate service
ng g m module-name Generate module
ng g p pipe-name Generate pipe
ng g d directive-name Generate directive
ng test Run unit tests
ng e2e Run end-to-end tests
ng lint Lint the project
ng update Update Angular packages

12.4 Recommended Learning Roadmap


1. Learn TypeScript basics first
2. Understand components, templates, data binding
3. Master routing and navigation
4. Learn reactive forms and HTTP client
5. Dive into RxJS and async patterns
6. Explore advanced topics: lazy loading, guards, interceptors
7. Learn state management with NgRx for large apps
8. Practice unit testing
9. Build real projects!

Happy Coding with Angular!


Official Docs: [Link]

You might also like