Monday, July 9, 2018

Angular


Step 1: Install Node.js and npm

  1. Download and install Node.js:

    • Go to the Node.js official website and download the LTS version.
    • Installing Node.js will also install npm (Node Package Manager) automatically.
  2. Verify the installation: Open a terminal or command prompt and run:

    node -v
    npm -v

    These commands will display the installed versions of Node.js and npm.

Step 2: Install Angular CLI

  1. Install Angular CLI globally: Run the following command in the terminal to install Angular CLI globally on your system:

    npm install -g @angular/cli
  2. Verify Angular CLI installation: After installation, check the version of the Angular CLI by running:

    ng version

Step 3: Create a New Angular Project

  1. Generate a new project: Use the Angular CLI to create a new project. Replace my-angular-app with your preferred project name:

    ng new my-angular-app

    The CLI will prompt you with several questions about setting up the project:

    • Routing: Select Yes if you want to add Angular routing.
    • Stylesheet format: Choose the stylesheet format you prefer (CSS, SCSS, SASS, etc.).
  2. Navigate to the project folder: After the project is generated, navigate into the project directory:

    cd my-angular-app

Step 4: Run the Development Server

  1. Start the Angular development server: To run the development server, use the following command:

    ng serve

    By default, the Angular CLI will start a local development server and watch for any file changes. The default address is http://localhost:4200.

  2. Open the application in the browser: Once the server is up, open your browser and go to http://localhost:4200. You should see the default Angular welcome page.

Optional: Run the Angular Server on a Different Port

If you want to run the server on a different port (e.g., port 4300), you can specify the port like this:

ng serve --port 4300

Step 5: Build the Application for Production (Optional)

When you're ready to deploy your application, build it for production using:

ng build --prod

This will create an optimized, minified version of your app in the dist/ directory, which you can then serve using any static file server.


Node:             20.17.0
Package Manager: npm 10.8.3
Angular CLI:    18.2.8
typescript:       5.5.4
rxjs:                7.8.1


For upgrade the angular application versions

npm-check-updates

ncu -u

npm install

npm update --all --save

npm audit fix --force


Here's a cheat sheet of main topics in Angular that covers the essential concepts, features, and tools you need to know.

1. Angular Modules

  • NgModule: Organizes code into cohesive blocks.
    • Core Module: AppModule is the root module where your app starts.
    • Feature Modules: Used to organize related components, services, and directives.
    • Example:
      @NgModule ({ declarations: [AppComponent], imports: [BrowserModule], bootstrap: [AppComponent] }) export class AppModule { }

2. Components

  • Component: A fundamental building block of Angular applications. Components control a part of the UI.
    • Decorators: @Component to define metadata.
    • Template & Styles: Use inline or external HTML and CSS files.
    • Example:
      ng g c component_name
      @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'my-angular-app'; }

3. Directives

  • Structural Directives: Modify the DOM structure.
    • *ngIf, *ngFor, *ngSwitch.
  • Attribute Directives: Modify the appearance or behavior of an element.
    • ngClass, ngStyle.
    • Custom Directives: Use @Directive decorator to create.
    Example:
    <div *ngIf="isLoggedIn">Welcome, user!</div> <ul> <li *ngFor="let item of items">{{ item }}</li> </ul>

4. Services & Dependency Injection

  • Service: A class that contains business logic, usually injected into components.
  • Dependency Injection: Provided via @Injectable() decorator.
    • Example:
      @Injectable({
      providedIn: 'root', }) export class DataService { getData() { return ['data1', 'data2']; } }

5. Routing & Navigation

  • RouterModule: Configures app routes and enables navigation between views.
  • Routes: Defined as a mapping between URL paths and components.
    • Example:
      const routes: Routes = [
      { path: 'home', component: HomeComponent }, { path: 'about', component: AboutComponent }, { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] }, { path: '', redirectTo: '/home', pathMatch: 'full' } { path: 'products', loadChildren: () => import('./products/products.module') .then(m => m.ProductsModule) } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
  • Router Outlet: Marks where the routed component should display.
    • Example: <router-outlet></router-outlet>
  • Router Link: 
         <a routerLink="/home">Home</a>
         <a [routerLink]="['../home']">Go to Home</a>
         
    <a [routerLink]="['/product', productId]">Product</a>
         <a [routerLink]="['/search']" [queryParams]="{ query: searchQuery }">Search</a>

    this.router.navigate(['/home']);
    this.router.navigate(['/product', productId]);
         
         

6. Forms

  • Reactive Forms: Form control defined in TypeScript with form validation.

    • FormGroup, FormControl, FormBuilder.
    • Example:
      form = new FormGroup({ name: new FormControl(''), email: new FormControl(''), });
  • Template-driven Forms: Use Angular’s directives in templates to create forms.

    • ngModel, ngForm for two-way data binding.
    • Example:
      <form #myForm="ngForm"> <input [(ngModel)]="name" name="name" required /> </form>

7. Data Binding

  • Interpolation: Binding data from the component to the template.
    • Example: {{ variableName }}
  • Property Binding: One-way data binding from component to DOM property.
    • Example: <img [src]="imageURL">
  • Event Binding: Binding an event in the DOM to a method in the component.
    • Example: <button (click)="doSomething()">Click me</button>
  • Two-way Binding: Combination of property and event binding using ngModel.
    • Example: <input [(ngModel)]="name">

8. Pipes

  • Pipes transform output in the template.
    • Built-in Pipes: DatePipe, UpperCasePipe, CurrencyPipe, AsyncPipe.
    • Custom Pipes: Use @Pipe decorator to create.
    • Example:
      {{ currentDate | date:'short' }}

9. HTTP Client

  • HttpClientModule: Module for making HTTP requests.
  • HttpClient: Service to handle GET, POST, PUT, DELETE requests.
    • Example:
      this.http.get('https://api.example.com/data') .subscribe(response => this.data = response);

10. Lifecycle Hooks

  • Methods that Angular calls during different phases of a component’s lifecycle:
    • ngOnInit(): Called after the component's initialization.
    • ngOnChanges(): Called when an input property changes.
    • ngOnDestroy(): Called just before the component is destroyed.

    Angular Lifecycle Stages and Hooks:

    1. Component Initialization

      • ngOnChanges: Called when the component’s input properties change. It is triggered before ngOnInit.
      • ngOnInit: Called once after the component is initialized (after the first ngOnChanges). This is typically where you initialize data or fetch resources needed for the component.
    2. Change Detection

      • ngDoCheck: Called during each change detection cycle. Useful if you need custom change detection logic.
      • ngAfterContentInit: Called after Angular projects external content into the component (via <ng-content>).
      • ngAfterContentChecked: Called after every change detection cycle, ensuring that the projected content has been checked.
      • ngAfterViewInit: Called after the component’s view (and its children) have been fully initialized.
      • ngAfterViewChecked: Called after every change detection cycle to check the view and its children again.
    3. Component Destruction

      • ngOnDestroy: Called just before the component is destroyed. This is where you clean up subscriptions, timers, or other resources to avoid memory leaks
    Example:
    ngOnInit() { console.log('Component initialized'); }

11. Change Detection

  • Angular’s mechanism for updating the view when the data in the component changes.
  • OnPush Strategy: Optimizes performance by checking for changes only when inputs change.

12. Lazy Loading

  • Load feature modules only when needed (on-demand) to optimize app performance.
    • Example:
      const routes: Routes = [ { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) } ];

13. Angular Material

  • A UI component library for Angular apps based on Google’s Material Design.
    • Installation:
      ng add @angular/material
    • Example usage:
      <mat-button>Click me!</mat-button>

14. Testing

  • Unit Testing: Angular uses Jasmine and Karma for unit tests.
    • Example:
      it('should create the app', () => { expect(component).toBeTruthy(); });
  • End-to-End (E2E) Testing: Angular uses Protractor (or Cypress) for E2E tests.

15. Angular CLI

  • Commands:
    • ng serve: Run the development server.
    • ng build: Build the project for production.
    • ng generate component component-name: Generate new components, services, etc.
    • ng test: Run unit tests.
    • ng lint: Run the linter for code quality checks.


Here's an overview of the Angular Long-Term Support (LTS) upgrade list, along with the major versions and key features introduced with each upgrade:

Angular LTS Versions and Features

Angular 2 (September 2016)

  • Initial Release of Angular as a complete rewrite of AngularJS.
  • Key Features:
    • Component-based architecture.
    • TypeScript as the primary language.
    • Dependency Injection (DI).
    • Angular CLI for scaffolding projects.
    • Ahead-of-Time (AOT) compilation.

Angular 4 (March 2017)

  • Backward compatibility with Angular 2 (Angular 3 was skipped).
  • Key Features:
    • Smaller and faster builds due to View Engine improvements.
    • Improved ngIf and ngFor with an else clause.
    • Animations moved to a separate @angular/animations module.
    • Improved support for TypeScript 2.1 and 2.2.

Angular 5 (November 2017)

  • Performance improvements and smaller bundles.
  • Key Features:
    • Build optimizer tool for faster and smaller production builds.
    • Angular Universal State Transfer API: Facilitates server-side rendering (SSR).
    • HttpClient: Replaces Http module with a new, more powerful HTTP client.
    • Internationalized number, date, and currency pipes.

Angular 6 (May 2018)

  • Focused on tooling improvements and reducing build complexity.
  • Key Features:
    • Angular Elements: Allows Angular components to be used as web components.
    • Service Worker Improvements for better PWA support.
    • Tree-shakeable providers to optimize bundle size.
    • ng add command for adding features (e.g., Material Design, AngularFire) to projects.
    • ng update command to simplify project dependencies updates.

Angular 7 (October 2018)

  • Minor improvements and optimizations.
  • Key Features:
    • CLI prompts for built-in Angular commands like ng add or ng new.
    • Virtual scrolling: Efficient rendering for large lists using the cdk-virtual-scroll-viewport.
    • Drag and Drop support from Angular Material and CDK.
    • Content Projection with ngTemplate and ngComponentOutlet improvements.

Angular 8 (May 2019)

  • Ivy Preview: Angular's new rendering engine introduced as an opt-in feature.
  • Key Features:
    • Differential Loading: Ships ES5 and ES2015 bundles automatically to optimize loading for modern browsers.
    • Dynamic Imports for lazy-loaded modules.
    • Web Worker support in CLI for improved app performance.
    • Bazel: Experimental build tool integration.

Angular 9 (February 2020)

  • Ivy: New rendering engine and compiler become the default.
  • Key Features:
    • Smaller bundle sizes and faster compilation.
    • Improved Type Checking.
    • Better debugging with ngForTrackBy improvements.
    • Internationalization (i18n) updates to support runtime inlining of translations.

Angular 10 (June 2020)

  • Primarily a polish release focusing on improvements and stability.
  • Key Features:
    • Optional Strict Mode for stricter type-checking and enhanced performance.
    • Date Range Picker in Angular Material.
    • ngcc (Angular Compatibility Compiler) enhancements to improve the performance of libraries.

Angular 11 (November 2020)

  • Focus on bug fixes, performance improvements, and community feedback.
  • Key Features:
    • Faster Builds with improved Hot Module Replacement (HMR).
    • Automatic font inlining during production builds.
    • Webpack 5 support (experimental).
    • Improved logging and reporting for build processes.

Angular 12 (May 2021)

  • Angular Ivy: Everything now works on Ivy, with no View Engine support.
  • Key Features:
    • Strict Mode becomes the default for new projects.
    • Nullish Coalescing (??) operator in templates.
    • Standalone Components (Experimental).
    • Deprecation of protractor for end-to-end testing.

Angular 13 (November 2021)

  • Removes View Engine entirely, making Ivy the sole rendering engine.
  • Key Features:
    • ESBuild: Modern JavaScript bundler replacing webpack for faster builds.
    • TypeScript 4.4 support with more strict typing.
    • Component APIs for cleaner, more efficient component creation.
    • Dynamic Component Creation without the need for ComponentFactoryResolver.

Angular 14 (June 2022)

  • Focused on developer experience and performance.
  • Key Features:
    • Standalone Components: Components, pipes, and directives no longer need a module.
    • Typed Forms: Reactive forms now support strongly-typed FormGroups and FormControls.
    • Extended Dependency Injection for optional injectors.
    • Angular DevTools: Integrated directly into the CLI for performance tracking.

Angular 15 (November 2022)

  • Stabilized Standalone APIs.
  • Key Features:
    • Directive Composition API: Compose directives with reusable logic.
    • Standalone API Improvements: Makes the standalone application model more practical for real-world projects.
    • Improved Router Handling: Lazy-loading and better handling of feature modules.
    • Angular Material: Expanded with new components and improved performance.

Angular 16 (May 2023)

  • First major release of Angular Signals (for reactivity model).
  • Key Features:
    • Zone.js optional: Signals remove the need for Zone.js.
    • Strong Typed Router for better navigation and route management.
    • Hydration Support: Improved server-side rendering (SSR) with hydration.
    • Control Flow in Templates: Better handling of ngIf and ngFor within templates.

Angular 17 (Expected November 2024)

  • Planned Features (speculative):
    • Improved Signals API: Signals will be enhanced further to improve performance and development speed.
    • Server-Client Symmetry: Further optimizations for SSR and hydration, likely to improve performance in PWAs.
    • More Reactive Forms Enhancements for typed forms and form state management.
    • Angular DevTools enhancements for better debugging and profiling.

Secure Angular Application:

  1. Use route guards (CanActivate,CanDeActivate,CanActivateChildCanLoad.) to control access.
  2. Implement role-based access control (RBAC) for different user roles.
  3. Use JWT tokens for secure authentication and send them with every request.
  4. Prevent URL Tampering (Client-Side Check Isn’t Enough)
    Always enforce security checks on the backend.
  5. Ensure HTTPS is used for all communications.
  6. Securely store sensitive data using HttpOnly cookies and avoid localStorage.
    Set-Cookie: token=jwt-token; HttpOnly; Secure; SameSite=Strict;
  7. Protect against XSS by sanitizing input and securing template bindings.
  8. Prevent clickjacking with X-Frame-Options.
    X-Frame-Options: DENY
  9. Use Content Security Policy (CSP) headers to control content sources.
    Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://trusted-cdn.com;
  10. Handle logout properly by clearing authentication tokens.
  11. Avoid open redirects that can lead users to untrusted websites.
  12. Avoid Hardcoding sensitive data in code
  13. Secure API with CORS
    Access-Control-Allow-Origin: https://your-angular-app.com
    Access-Control-Allow-Credentials: true

Using canActivate:

Command:   ng g guard services/auth

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service'; // Auth service that manages authentication state

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) {}

  canActivate(): boolean {
    if (this.authService.isLoggedIn()) {
      return true;
    } else {
      this.router.navigate(['/login']);
      return false;
    }
  }
}

// In your routing module:
const routes: Routes = [
  {
    path: 'dashboard',
    component: DashboardComponent,
    canActivate: [AuthGuard] // Protect the route
  },
  {
    path: 'login',
    component: LoginComponent
  }
];


Role-Based Authorization with CanActivate

@Injectable({
  providedIn: 'root'
})
export class RoleGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot): boolean {
    const expectedRole = route.data['expectedRole'];
    const userRole = this.authService.getUserRole();

    if (userRole === expectedRole) {
      return true;
    } else {
      this.router.navigate(['/unauthorized']);
      return false;
    }
  }
}

// In your routing module:
const routes: Routes = [
  {
    path: 'admin',
    component: AdminComponent,
    canActivate: [RoleGuard],
    data: { expectedRole: 'admin' } // Protect admin routes
  }
];


 

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service'; // Auth service to get the token

@Injectable()
export class TokenInterceptor implements HttpInterceptor {
  constructor(private authService: AuthService) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = this.authService.getToken();

    if (token) {
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${token}` // Add JWT to request headers
        }
      });
    }

    return next.handle(request);
  }
}

Ways to Pass Data in Angular:

  1. @Input() and @Output() (Parent-Child Communication)
  2. Service with Dependency Injection (For Sibling and Unrelated Components)
  3. @ViewChild and @ViewChildren (Access Child Component API)
  4. @ContentChild and @ContentChildren (Access Projected Content)
  5. Route Parameters (Passing Data via URL)
  6. LocalStorage/SessionStorage (Persistent Data Storage)
  7. RxJS Subjects (Reactive Data Sharing)


1. @Input() and @Output() Decorators (Parent to Child and Child to Parent Communication)

1.1 @Input() (Parent to Child)

  • Pass data from a parent component to a child component.
  • The parent component binds data to a property of the child component using the @Input() decorator.

Example:


// Child Component import { Component, Input } from '@angular/core'; @Component({ selector: 'app-child', template: `<p>{{ childMessage }}</p>` }) export class ChildComponent { @Input() childMessage: string; // Receive data from parent } // Parent Component @Component({ selector: 'app-parent', template: `<app-child [childMessage]="parentMessage"></app-child>` }) export class ParentComponent { parentMessage = "Hello from Parent!"; }

1.2 @Output() and EventEmitter (Child to Parent)

  • Pass data from a child component to a parent component using an event.
  • The child component emits an event via @Output(), and the parent listens for the event.

Example:

// Child Component import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-child', template: `<button (click)="sendData()">Send Data to Parent</button>` }) export class ChildComponent { @Output() messageEvent = new EventEmitter<string>(); sendData() { this.messageEvent.emit('Hello from Child!'); } } // Parent Component @Component({ selector: 'app-parent', template: `<app-child (messageEvent)="receiveMessage($event)"></app-child><p>{{ message }}</p>` }) export class ParentComponent { message: string; receiveMessage($event: string) { this.message = $event; } }

2. Service with Dependency Injection (Sibling and Unrelated Components)

  • Services can be used to share data between components that are not directly related, such as sibling components or across the entire application.
  • You can create a shared service and inject it into the components that need to share data.

Example:

// Shared Service
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root', }) export class DataService { private messageSource = new BehaviorSubject<string>('default message'); currentMessage = this.messageSource.asObservable(); changeMessage(message: string) { this.messageSource.next(message); } } // Component 1 @Component({ selector: 'app-component1', template: `<button (click)="newMessage()">Send Message</button>` }) export class Component1 { constructor(private dataService: DataService) {} newMessage() { this.dataService.changeMessage('Hello from Component 1!'); } } // Component 2 @Component({ selector: 'app-component2', template: `<p>{{ message }}</p>` }) export class Component2 { message: string; constructor(private dataService: DataService) {} ngOnInit() { this.dataService.currentMessage.subscribe(message => this.message = message); } }

3. @ViewChild and @ViewChildren (Parent to Child Communication with Access to Child Component API)

  • @ViewChild allows a parent component to directly access the child component’s methods and properties.
  • @ViewChildren is used when accessing multiple child components.

Example:

// Child Component
@Component({ selector: 'app-child', template: `<p>{{ message }}</p>` }) export class ChildComponent { message: string = 'Initial Message'; updateMessage(newMessage: string) { this.message = newMessage; } } // Parent Component @Component({ selector: 'app-parent', template: `<app-child></app-child><button (click)="changeChildMessage()">Change Child Message</button>` }) export class ParentComponent { @ViewChild(ChildComponent) childComponent: ChildComponent; changeChildMessage() { this.childComponent.updateMessage('Message changed by Parent'); } }

4. @ContentChild and @ContentChildren (For Projected Content in ng-content)

  • Use @ContentChild and @ContentChildren to get a reference to a child component or template passed through ng-content.

Example:

// Parent Component (Projected Content)
@Component({ selector: 'app-parent', template: ` <app-child> <p #projectedContent>Projected Content from Parent</p> </app-child> ` }) export class ParentComponent {} // Child Component @Component({ selector: 'app-child', template: `<ng-content></ng-content>` }) export class ChildComponent { @ContentChild('projectedContent') projected: ElementRef; ngAfterContentInit() { console.log(this.projected.nativeElement.textContent); // Access projected content } }

Route Parameters (Passing Data via the URL)
Angular’s Router allows you to pass data through route parameters.

5.1 Passing Data via Path Parameters

  • Data can be passed through the URL in the form of path parameters.


// Router Configuration
const routes: Routes = [
  { path: 'user/:id', component: UserComponent }
];

// In the component, access the route parameter:
@Component({
  selector: 'app-user',
  template: `<p>User ID: {{ userId }}</p>`
})
export class UserComponent implements OnInit {
  userId: string;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.userId = this.route.snapshot.paramMap.get('id');
  }
}

5.2 Passing Data via Query Parameters

  • Query parameters are appended to the URL and passed along with the route.

Example:

// Navigate with query parameters this.router.navigate(['/user'], { queryParams: { id: 123, name: 'John' }}); // In the receiving component, access query parameters: @Component({ selector: 'app-user', template: `<p>ID: {{ id }}, Name: {{ name }}</p>` }) export class UserComponent implements OnInit { id: string; name: string; constructor(private route: ActivatedRoute) {} ngOnInit() { this.route.queryParams.subscribe(params => { this.id = params['id']; this.name = params['name']; }); } }

LocalStorage/SessionStorage (Persistence Across Sessions)

Data can be stored in localStorage or sessionStorage for persistence across browser sessions.
// Save data to localStorage
localStorage.setItem('username', 'JohnDoe');

// Retrieve data from localStorage
const username = localStorage.getItem('username');

// Remove data from localStorage
localStorage.removeItem('username');



Using BehaviorSubject/Subject (RxJS for Data Streams)
You can use RxJS subjects like Subject, BehaviorSubject, ReplaySubject, and AsyncSubject to share data as a stream of values between components.

import { BehaviorSubject } from 'rxjs';

export class SharedService {
  private messageSource = new BehaviorSubject<string>('Initial Message');
  currentMessage = this.messageSource.asObservable();

  changeMessage(message: string) {
    this.messageSource.next(message);
  }
}

Operators:

  • |: Pipe operator for transforming data in Angular templates.
  • ?.: Safe navigation (Elvis operator) to safely access properties of potentially null/undefined objects.
  • !: Non-null assertion operator to assert that a value is not null or undefined.
  • ??=: Logical nullish assignment operator, assigns value only if the variable is null or undefined.
  • &&: Logical AND, short-circuits if the first condition is false.
  • ||: Logical OR, returns the first truthy value.
  • !== and ===: Strict inequality and equality operators for comparing values and types.
  • <, <=, >, >=: Comparison operators to evaluate conditions.
  • ??: Nullish coalescing operator to return a default value if the left operand is null/undefined.
  • &, |: Bitwise AND and OR, used for integer comparisons.
  • ...: Spread operator for expanding arrays or objects.
  • $: A naming convention to denote variables that are Observables in Angular and RxJS. It helps improve code clarity by indicating the presence of an asynchronous data stream.
  • *: Used with structural directives in Angular templates, such as *ngIf, *ngFor, and *ngSwitch, to conditionally include or repeat elements in the DOM. The * is shorthand for ng-template.






    Angular Signals:

    Eg:
    Big house(Complex application) with tons of rooms(components),
    Need to deduct which room has change

    If we search each and every room for the change ==> zone
    If we find where exact room have this change ==> Signals.

    Angular Signals

    1. Signals (Reactive Values): Signals hold values and can be watched for changes. When the value changes, the signal automatically notifies any subscribers.

      • Example:

        import { signal } from '@angular/core'; const count = signal(0); // A signal that holds the value 0 // Access the value console.log(count()); // Output: 0 // Update the value count.set(5); // Signal now holds 5
    2. Effect: Effects are reactive functions that run whenever the signals they depend on change. This enables you to perform side effects in response to reactive data updates.

      • Example:

        import { effect } from '@angular/core'; const count = signal(0); // Create an effect that runs whenever `count` changes effect(() => { console.log(`Count has changed to: ${count()}`); }); // Update the signal, which triggers the effect count.set(10); // Logs: "Count has changed to: 10"
    3. Computed: A computed value is derived from one or more signals. When any of the signals used in the computation change, the computed value is automatically recalculated.

      • Example:

        import { signal, computed } from '@angular/core'; const price = signal(100); const quantity = signal(2); // Computed signal const total = computed(() => price() * quantity()); console.log(total()); // Output: 200 // Update the price, the total is automatically recalculated price.set(150); console.log(total()); // Output: 300

    Why Angular Signals Matter

    • Fine-grained reactivity: Signals allow Angular to react to state changes at a granular level, leading to fewer unnecessary component re-renders and better performance.

    • Better control: Instead of relying on Angular’s global change detection, developers can control when state changes are detected and handled. This reduces overhead, especially in large applications.

    • Elimination of Zone.js: With signals, Angular applications can move away from Zone.js for change detection, enabling better performance, especially for CPU-intensive applications or apps with complex user interactions.

    • Predictable Reactivity: The reactive nature of signals makes it clear when a change will trigger updates, which improves the predictability of the application’s state management.

    Comparison: Signals vs. Traditional Angular Change Detection

    FeatureTraditional Change Detection (Zone.js)Signals
    Reactivity ModelGlobal, automatic via Zone.jsFine-grained, explicit with signals
    PerformanceCan be inefficient in large appsOptimized for minimal updates
    Change Detection CycleRuns across all componentsOnly runs for signal dependencies
    ComplexityLess control over when changes occurExplicit control of reactivity
    UsageUses Angular templates and lifecycle hooksWorks directly with state and values

    Example: Angular Signals in Components

    Here’s how Angular Signals might be used in a component:


    import { Component, signal, computed, effect } from '@angular/core'; @Component({ selector: 'app-counter', template: ` <div> <p>Current Count: {{ count() }}</p> <p>Total: {{ total() }}</p> <button (click)="increment()">Increment</button> </div> `, }) export class CounterComponent { count = signal(0); multiplier = signal(2); // Computed value: total total = computed(() => this.count() * this.multiplier()); constructor() { // Effect: log whenever count changes effect(() => { console.log(`Count updated to: ${this.count()}`); }); } increment() { this.count.set(this.count() + 1); } }

    Use Cases for Angular Signals

    • State management: Signals can replace services like BehaviorSubject or EventEmitter for state management.
    • Efficient UI updates: Signals help update only the parts of the UI that depend on changed data, reducing unnecessary re-renders.
    • Reactive Forms: Signals can be used to build reactive form validation and state management without using complex RxJS operators.
    • Performance-sensitive applications: Signals offer more control over when state changes are detected, which improves performance for applications that need frequent or high-volume updates.

    Future Outlook for Angular Signals

    Signals are part of a broader effort by the Angular team to make the framework more reactive and modular. They will likely form the basis of the future Angular reactivity model, gradually phasing out Zone.js and reducing the complexity of change detection.


    In Angular, managing data flow, handling observables, and controlling component interactions are essential concepts. Here's a detailed overview of the topics you mentioned:

    1. Subjects in Angular

    Subjects in Angular are a special type of Observable from RxJS. They allow you to multicast values to multiple observers and actively push values.

    Types of Subjects:

    • Subject:

      • Basic subject that can both emit and subscribe to data.
      • It’s like an Observable but with the ability to actively emit values using the next() method.
      typescript
      const subject = new Subject<number>(); subject.subscribe(value => console.log('Observer 1:', value)); subject.subscribe(value => console.log('Observer 2:', value)); subject.next(1); // Both observers receive the value subject.next(2); // Both observers receive the value again
    • BehaviorSubject:

      • Similar to Subject, but it stores the current value. It requires an initial value and will emit the current value to new subscribers.
      typescript
      const behaviorSubject = new BehaviorSubject<number>(0); // Initial value: 0 behaviorSubject.subscribe(value => console.log('Observer 1:', value)); behaviorSubject.next(1); // Emits 1 behaviorSubject.subscribe(value => console.log('Observer 2:', value)); // Observer 2 gets 1
    • ReplaySubject:

      • Stores a set number of previous emissions and replays them to new subscribers.
      typescript
      const replaySubject = new ReplaySubject<number>(2); // Stores the last 2 values replaySubject.next(1); replaySubject.next(2); replaySubject.next(3); replaySubject.subscribe(value => console.log('Observer:', value)); // Receives 2, 3
    • AsyncSubject:

      • Emits the last value upon completion of the subject. Subscribers only receive the last emitted value when the complete() method is called.
      typescript
      const asyncSubject = new AsyncSubject<number>(); asyncSubject.next(1); asyncSubject.next(2); asyncSubject.complete(); // Emits 2 to all subscribers

    2. Signals (Introduced in Angular 16+)

    Signals are a reactive programming model introduced in Angular for more efficient state management and UI reactivity. They represent values that can be read, and automatically notify any consumers when they change.

    • Reading signals: Using signal.get().
    • Writing signals: Using signal.set() or signal.update() to modify values reactively.

    Angular Signals are still in development and have been aimed to reduce change detection overhead, making Angular apps more performant by allowing more explicit reactivity.

    typescript
    const count = signal(0); // Reading the signal console.log(count()); // Prints 0 // Updating the signal count.set(1); console.log(count()); // Prints 1 count.update((value) => value + 1); console.log(count()); // Prints 2

    3. Guards in Angular

    Guards are used to control access to routes in Angular. They are implemented as services and return true or false based on certain conditions, determining if navigation is allowed.

    Common Guards:

    • CanActivate: Determines whether a route can be activated.
    • CanDeactivate: Checks if a user can leave a route (useful for unsaved form data).
    • Resolve: Pre-fetches data before the route is activated.
    • CanLoad: Checks if a module can be lazily loaded.

    Example of a CanActivate Guard:

    typescript
    @Injectable({ providedIn: 'root', }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate(): boolean { if (this.authService.isLoggedIn()) { return true; } else { this.router.navigate(['/login']); return false; } } }

    4. Observers in Angular

    Observers are simply objects that subscribe to observables and handle the emitted values. They consist of three methods:

    • next(): Receives the emitted value.
    • error(): Handles errors.
    • complete(): Called when the observable completes.
    typescript
    const observable = new Observable(observer => { observer.next('Hello World'); observer.complete(); }); const observer = { next: value => console.log('Value:', value), error: err => console.error('Error:', err), complete: () => console.log('Completed') }; observable.subscribe(observer);

    5. Event Emitters in Angular

    EventEmitter is a class in Angular used to emit custom events within components, often between parent-child components.

    • Parent to Child communication is done using @Input().
    • Child to Parent communication is achieved using EventEmitter with @Output().

    Example of EventEmitter for child-to-parent communication:

    typescript
    @Component({ selector: 'child-component', template: `<button (click)="sendData()">Send Data</button>`, }) export class ChildComponent { @Output() dataEvent = new EventEmitter<string>(); sendData() { this.dataEvent.emit('Data from child'); } } @Component({ selector: 'parent-component', template: `<child-component (dataEvent)="receiveData($event)"></child-component>`, }) export class ParentComponent { receiveData(data: string) { console.log(data); // Logs: Data from child } }

    6. Subscribe in Angular

    subscribe() is a method used to handle data emitted by Observables. Subscriptions are crucial in Angular to listen to asynchronous data streams like HTTP requests, WebSocket connections, or event streams.

    typescript
    const observable = of(1, 2, 3); observable.subscribe({ next: value => console.log(value), // Handle each emitted value error: err => console.error('Error:', err), // Handle error complete: () => console.log('Completed') // Handle completion });

    In the context of Angular services and HTTP requests:

    typescript
    this.httpClient.get('/api/data').subscribe(data => { console.log(data); });

    7. Async Pipe in Angular

    The AsyncPipe is used in Angular templates to automatically subscribe to an observable and display its emitted values. It also handles unsubscription automatically when the component is destroyed.

    html
    <div *ngIf="data$ | async as data"> {{ data }} </div>

    Summary of Angular Concepts

    1. Subjects: Multicasting observables (Subject, BehaviorSubject, ReplaySubject, AsyncSubject) for handling shared streams of data.
    2. Signals: Reactive programming approach introduced in Angular to manage explicit reactivity.
    3. Guards: Used to secure routes and control access to different parts of an application.
    4. Observers: Handle observable data streams with next, error, and complete methods.
    5. Event Emitters: Emit custom events for component communication, particularly from child to parent.
    6. Subscribe: The method used to receive values from observables in services or components.
    7. Async Pipe: Used in templates to handle subscriptions automatically and manage asynchronous data.

    Together, these concepts allow Angular developers to manage state, route control, component communication, and asynchronous data efficiently.

    Differences Between Signals, Observers, and Subjects:

    FeatureSignalsObservables (Observers)Subjects
    NatureTracks and stores a single reactive valueStream of data over timeAllows emitting and receiving data manually
    Reactivity ModelPull-based (consumers get notified when value changes)Push-based (values are emitted to subscribers)Push-based (values are manually emitted to subscribers)
    SubscriptionsNo subscriptions (Angular handles updates automatically)Requires manual subscription (subscribe())Also requires manual subscription
    Emitting ValuesManually updated with .set() or .update()Emissions happen within the observable streamValues manually emitted using next()
    Change DetectionAutomatically triggers UI updates when value changesDoes not directly trigger Angular UI updates, needs async pipe or manual handlingSame as Observables, but multicasts to many subscribers
    Use CasesComponent state management, automatic UI reactivityHandling asynchronous data (like HTTP requests, event streams)Event-driven architecture, multicast data sharing

  • Interview Questions for Angular (Experienced)

    1. Architecture and Core Concepts

    • What is Angular and how is it different from AngularJS?
    • Can you explain the architecture of an Angular application?
    • What is the role of NgModule in Angular?
    • How does dependency injection work in Angular, and why is it important?
    • What are the different types of directives in Angular, and how do they differ?
    • Explain the purpose of @Input() and @Output() decorators.
    • What are Angular Pipes, and how would you create a custom pipe?

    2. Data Binding and Component Interaction

    • Explain the different types of data binding in Angular (one-way, two-way, property binding, event binding).
    • How does Angular handle two-way data binding using [(ngModel)]?
    • How do you communicate between parent and child components?
    • What is an EventEmitter and how do you use it?
    • How can you implement shared state or service-based communication between non-related components?

    3. Forms in Angular

    • What are template-driven forms and reactive forms in Angular? How do they differ?
    • How would you validate forms in Angular (both client-side and server-side)?
    • Can you explain how form validation is handled in reactive forms?
    • How do you use FormBuilder and why would you use it over manually creating FormControl and FormGroup?

    4. Angular Services and Dependency Injection

    • How do services work in Angular, and what is the role of Injectable()?
    • What is the difference between providing a service in a module vs. in a component?
    • Can you explain the different scopes of service providers in Angular (root, platform, any)?
    • What are hierarchical injectors and how do they impact dependency injection?

    5. Routing and Navigation

    • How does Angular’s routing work, and how would you implement lazy loading of routes?
    • What are route guards? Can you explain CanActivate, CanDeactivate, and Resolve guards?
    • How would you handle route parameters in Angular? How do ActivatedRoute and Router services work?
    • What is the router-outlet directive and how does it work?

    6. Observables, RxJS, and Async Operations

    • What is an Observable in Angular, and how is it different from a Promise?
    • Explain the role of RxJS in Angular and give examples of common RxJS operators like map(), switchMap(), mergeMap(), debounceTime().
    • How would you handle HTTP requests in Angular using HttpClient? How does the HttpInterceptor work?
    • Explain the difference between Subject, BehaviorSubject, ReplaySubject, and AsyncSubject.
    • What is the async pipe in Angular, and how does it help in template binding?

    7. Performance Optimization

    • How would you optimize the performance of an Angular application?
    • What are the best practices for handling change detection in Angular?
    • How does OnPush change detection strategy work, and when would you use it?
    • What are the benefits of using lazy loading in Angular?
    • How can you prevent memory leaks in an Angular application?

    8. Error Handling and Testing

    • How do you handle errors in Angular? What are the best practices for global error handling?
    • What is an Angular ErrorHandler, and how would you implement a custom error handler?
    • How do you test Angular components, services, and modules?
    • What is TestBed in Angular testing, and how is it used?
    • How do you perform unit tests and end-to-end (E2E) tests in Angular using tools like Jasmine, Karma, and Protractor?

    9. State Management and NgRx

    • What is NgRx, and how does it help with state management in Angular?
    • Can you explain the concepts of actions, reducers, and effects in NgRx?
    • How do you manage component state without NgRx or Redux in Angular?
    • What are selectors, and how do they help optimize state management in NgRx?

    10. Newer Concepts in Angular (Optional)

    • What are signals in Angular (introduced in Angular 16+)? How do they differ from observables?
    • How do standalone components work in Angular?
    • Explain how the declarative UI model in Angular improves performance and maintainability.

    Core Issues in Angular

    1. Change Detection Overhead

    • Issue: Angular's default change detection runs on every event, potentially causing performance issues in large applications.
    • Solution: Use the OnPush change detection strategy to limit unnecessary checks. Employ immutability to optimize reactivity.

    2. Memory Leaks

    • Issue: Unsubscribed observables can cause memory leaks in Angular, especially in large or long-lived applications.
    • Solution: Use takeUntil, unsubscribe(), or AsyncPipe to ensure that subscriptions are properly disposed of.

    3. Performance Bottlenecks with Large Applications

    • Issue: Angular applications with a lot of components, services, and modules can suffer from performance bottlenecks.
    • Solution: Implement lazy loading of modules, reduce bundle sizes using the Angular CLI’s ng build --prod, and use tree shaking to remove unused code.

    4. Route Guard Handling

    • Issue: Improper or overuse of route guards can lead to complex navigation flows and debugging issues.
    • Solution: Clearly define route guarding strategies, and use guards only when necessary for security, lazy loading, or pre-fetching data.

    5. Poor State Management

    • Issue: Improper handling of state across components can lead to issues such as inconsistent UI states, performance problems, and complex debugging.
    • Solution: Use centralized state management solutions like NgRx or implement shared services for small-to-medium state requirements.

    6. Slow Initial Loading Time (Lazy Loading and Preloading)

    • Issue: Angular applications can have slow initial load times due to large bundle sizes.
    • Solution: Implement lazy loading for feature modules and preloading strategies for essential modules to balance load time with usability.

    7. Mismanagement of Forms (Reactive vs. Template-Driven)

    • Issue: Poor handling of forms, especially in complex applications, can lead to unmanageable code and validation issues.
    • Solution: Use Reactive Forms for complex forms with dynamic validations and Template-Driven Forms for simpler use cases.

    8. Inconsistent Error Handling

    • Issue: Not implementing a proper error-handling mechanism can lead to uncaught runtime errors, poor UX, and debugging challenges.
    • Solution: Use Angular’s global error handling via the ErrorHandler service. Implement error handling at the service and component level for better control.

    9. Misuse of Third-Party Libraries

    • Issue: Overuse of third-party libraries, without proper understanding, can introduce compatibility issues and bloated bundle sizes.
    • Solution: Minimize the use of third-party libraries by relying on Angular’s core features and modular approach, and ensure libraries are up-to-date and actively maintained.

    10. Improper HTTP Handling

    • Issue: Handling multiple HTTP requests inefficiently can cause performance issues, such as unnecessary API calls or race conditions.
    • Solution: Use Angular’s HttpClient with RxJS operators like mergeMap, concatMap, or forkJoin for more efficient handling of multiple API requests.

    No comments:

    Security Certificates

      1. Cryptography Basics Understand Key Concepts : Encryption, decryption, hashing, and digital signatures. Key terms: confidentiality, inte...