Skip to content

Instantly share code, notes, and snippets.

@CodeByKwakes
Last active July 12, 2024 20:40
Show Gist options
  • Save CodeByKwakes/4f52c5d5be1f43a7fa8bb021a6a6e1bb to your computer and use it in GitHub Desktop.
Save CodeByKwakes/4f52c5d5be1f43a7fa8bb021a6a6e1bb to your computer and use it in GitHub Desktop.
Learn Angular #angular

Learn Angular

npm npm npm npm

Contents

Introduction

Angular is a platform and framework for building single-page client applications using HTML and TypeScript.

Difference between AngularJS vs Angular

AngularJS Angular
Based on MVC Architecture Based on Components
Uses JavaScript to build the application Uses TypeScript to build the application
No Mobile Support Mobile supports
Run on only client-side Runs on both client-side as well as server-side
CLI not present CLI present
No SEO Friendly Seo Friendly

Roadmap

https://roadmap.sh/angular

Configuration

Prerequisites

  • Node.js

Installation

Install the Angular CLI globally:

npm install -g @angular/cli

Check version

ng version

Create workspace:

ng new <PROJECT_NAME>

Run the application:

cd <PROJECT NAME>
ng serve

Components

Component is the main building block of an Angular Application.

Three main building blocks

  • Template
  • Class
  • Metadata

Template - Defines the layout and content of the View.

Class - Class provides the data & logic to the View.

MetaData - Metadata Provides additional information about the component to the Angular.

Component metadata properties

  • Selector
  • Providers
  • Styles
  • StyleUrls
  • Template
  • TemplateUrl

Selector - Defines the element name or CSS selector that identifies the component in the HTML template.

Providers - Defines the providers of the component's dependencies.

styles - Defines the inline styles for the component.

styleUrls - Defines an array of URLs of the stylesheets for the component.

template - Defines the HTML template for the component.

templateUrl - Defines the URL of the HTML template for the component.

Component Creation

Steps are:

  1. Navigate to your Angular project directory.

  2. Create a new file, <component-name>.component.ts.

  3. At the top of the file, add the following import statement.

    import { Component } from '@angular/core';
  4. After the import statement, add a @Component decorator.

    @Component({
    })
  5. Choose a CSS selector for the component.

    @Component({
      selector: 'test-component',
    })
  6. Define the HTML template that the component uses to display information. In most cases, this template is a separate HTML file.

    @Component({
      selector: 'test-component',
      templateUrl: './test-component.component.html',
    })
  7. Select the styles for the component's template. In most cases, you define the styles for your component's template in a separate file.

    @Component({
      selector: 'test-component',
      templateUrl: './component.component.html',
      styleUrls: ['./component.component.css']
    })
  8. Add a class statement that includes the code for the component.

    export class TestComponent {
    
    }
  9. Register the Component in Angular Module -

    import { TestComponent } from './app.component';
    @NgModule({ 
      declarations: [ TestComponent ]
    })

Complete code for the component creation

//test-component.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'test-component',
  templateUrl: './component.component.html',
  styleUrls: ['./component.component.css']
})

export class TestComponent {

}
//app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
 
import { AppComponent } from './app.component';
import { TestComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent,
    TestComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Creating the inline Template & StyleUrls -

import { Component } from '@angular/core';
 
@Component({
  selector: 'app-root',
  template: '<h1> {{title}} works </h1>',
  styles: ['h1 { font-weight: bold; }']
})
export class AppComponent {
  title = 'app';
}

Back to top⤴️

Data binding

One way binding

a. From Component to View

Interpolation -

<h1>{{ firstText }} {{ lastText }}</h1>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  firstText = 'Interpolation';
  lastText = 'Example';
}

Stackblitz Example

Property binding - This allows for binding a property of an HTML element to a property in the component's class. It is denoted by square brackets ([]).

<h1 [innerText]="title"></h1>

<button [disabled]="isDisabled">I am disabled</button>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'Angular Property Binding Example';

  isDisabled = true;
}

Stackblitz Example

class binding

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  isActive = false;

  toggleActive() {
    this.isActive = !this.isActive;
  }
}
<div [class.active]="isActive">This div is active.</div>
<button (click)="toggleActive()">Toggle Active</button>
.active {
  background-color: yellow;
}

Stackblitz Example

style binding

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  backgroundColor = 'red';
  textColor = 'white';
}
<div [style.background-color]="backgroundColor">
  <h1 [style.color]="textColor">Hello, world!</h1>
</div>

Stackblitz Example

attribute binding

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  imageUrl = 'https://example.com/image.jpg';
  imageAlt = 'Example image';
  isButtonDisabled = false;
}
<img [attr.src]="imageUrl" [attr.alt]="imageAlt">
<button [attr.disabled]="isButtonDisabled">Click me</button>

Stackblitz Example

b. From View to Component

Event binding - This allows for binding an event of an HTML element to a method in the component's class. It is denoted by parentheses (()).

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  onClick() {
    console.log('Button was clicked');
  }
}
<h1>Event Binding Example</h1>
<button (click)="onClick()">Click me</button>

Stackblitz Example

Remeber💡

The (click) calls the specified function when a user clicks on the given element (in your example, when a user clicks on a row).

The (change) event binds to HTML's onChange event. This event is fired for `<input>`, `<select>`, and `<textarea>` elements when a change to the element's value is committed by the user.

The (change) event can also be specifically implemented by other Angular components. It is generally implemented on components where the contents of the component are changed by the user.

☝️Source of Explaination

Two ways binding

This allows for binding a property of an HTML element to a property in the component's class and vice-versa. This is done by using a combination of property binding and event binding. It is denoted by [(ngModel)].

ngModel -

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  name: string = '';
}
<input [(ngModel)]="name" placeholder="Enter your name">
<p>Your name is: {{name}}</p>

Stackblitz Example

Back to top⤴️

Directives

Directives add behaviour to an existing DOM element or an existing component instance.

Structural Directives

ngFor -

<h1>ngFor Example</h1>
<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  items = ['item 1', 'item 2', 'item 3'];
}

ngSwitch -

<h1>ngSwitch Example</h1>
<div [ngSwitch]="value">
  <div *ngSwitchCase="1">Case 1</div>
  <div *ngSwitchCase="2">Case 2</div>
  <div *ngSwitchCase="3">Case 3</div>
  <div *ngSwitchDefault>Default case</div>
</div>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  value = 1;
}

ngIf -

<h1>ngIf Example</h1>
<div *ngIf="showElement">
  This element will only be displayed if showElement is true.
</div>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  showElement = true;
}

Attribute Directives

ngModel -

<h1>ngModel Example</h1>
<form>
  <label for="name">Name:</label>
  <input type="text" id="name" [(ngModel)]="name" name="name" />
</form>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  name: string;
}

ngClass -

<h1>ngClass Example</h1>
<div [ngClass]="{ highlighted: isHighlighted }">
  This element will have the 'highlighted' class if isHighlighted is true.
</div>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  isHighlighted = true;
}

ngStyle -

<h1>ngStyle Example</h1>
<div [ngStyle]="{ color: color }">
  This element will have the color style set to the value of the color property.
</div>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  color = 'red';
}

Custom Directives

<h1>Custom Directive Element</h1>
<div appCustomDirective>
  This element will have a yellow background when the mouse is over it.
</div>
import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[appCustomDirective]',
})
export class CustomDirectiveDirective {
  constructor(private el: ElementRef) {}

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight('yellow');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { CustomDirectiveDirective } from './custom-directive.directive';

@NgModule({
  imports: [BrowserModule, FormsModule],
  declarations: [AppComponent, CustomDirectiveDirective],
  bootstrap: [AppComponent],
})
export class AppModule {}

Back to top⤴️

Other directives

  1. ngContainer

    The ngContainer directive is a simple container that doesn't generate any markup in the DOM. It's mainly used as a placeholder to group and structure content within Angular templates. It's particularly helpful when you need to apply structural directives like ngIf or ngFor to a group of elements without adding an extra wrapping element.

    <div *ngIf="condition">
      <ng-container>
        <p>Content to be conditionally rendered</p>
        <p>More content...</p>
      </ng-container>
    </div>

    In the above example, the ng-container acts as a grouping element for the conditional content, allowing you to apply the ngIf directive without introducing an extra <div> element.

  2. ngTemplate

    The ngTemplate directive is used to define a reusable template block that can be used later within the same component or shared across components using the ngTemplateOutlet directive. It allows you to define a template without rendering it immediately.

    <ng-template #myTemplate>
      <p>This is a template</p>
      <p>It can be reused in multiple places</p>
    </ng-template>
    
    <!-- Usage of the template -->
    <div>
      <ng-container *ngTemplateOutlet="myTemplate"></ng-container>
    </div>

    In the above example, the ng-template defines a template block named myTemplate. Later, within the same component, the ngTemplateOutlet directive is used to render the template inside a <div>.

  3. ngContent

    The ngContent directive is used for content projection or transclusion. It allows you to create reusable components with customizable content. By using ngContent, you can define placeholders in the component's template where external content can be inserted.

      <!-- Parent Component -->
      <app-child>
        <p>Content projected into the child component</p>
      </app-child>
    
      <!-- Child Component Template -->
      <div>
        <ng-content></ng-content>
      </div>

    In the above example, the <app-child> component has a <ng-content> tag in its template. When the component is used, the content provided between the opening and closing tags of the component is projected into the ng-content placeholder.

  4. ngTemplateOutlet

    The ngTemplateOutlet directive is used to render a template defined using ngTemplate. It allows you to dynamically render a template within a component's template.

    <ng-container *ngTemplateOutlet="selectedTemplate"></ng-container>
    
    <ng-template #template1>
      <!-- Template 1 content -->
    </ng-template>
    
    <ng-template #template2>
      <!-- Template 2 content -->
    </ng-template>
    
    <button (click)="selectedTemplate = template1">Load Template 1</button>
    <button (click)="selectedTemplate = template2">Load Template 2</button>

    In the above example, clicking the "Load Template 1" button will render the content from template1 within the <ng-container>, and clicking the "Load Template 2" button will render the content from template2. The selectedTemplate property is bound to the ngTemplateOutlet directive, dynamically selecting and rendering the chosen template.

Pipes

A pipe takes in data as input and transforms it to a desired output.

Syntax

Expression | pipeOperator[:pipeArguments]

# Expression: is the expression, which you want to transform
# | : is the Pipe Character
# pipeOperator : name of the Pipe
# pipeArguments: arguments to the Pipe

Date Pipe

<h1>Date Pipe Example</h1>
<p>{{ date | date: 'shortDate' }}</p>
import { DatePipe } from '@angular/common';
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  date = new Date();

  constructor(private datePipe: DatePipe) {}

  formatDate() {
    return this.datePipe.transform(this.date, 'shortDate');
  }
}
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { DatePipe } from '@angular/common';

@NgModule({
  imports: [BrowserModule, FormsModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [DatePipe],
})
export class AppModule {}

Uppercase Pipe

<h1>Upper Case Pipe Example</h1>
<p>{{ name | uppercase }}</p>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  name = 'Manthan Ank';
}

Lowercase Pipe

<p>{{ name | lowercase }}</p>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  name = 'Manthan Ank';
}

Currency Pipe

<h1>Currency Pipe Example</h1>
<p>{{ price | currency }}</p>
import { CurrencyPipe } from '@angular/common';
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  price = 100;

  constructor(private currencyPipe: CurrencyPipe) { }

  formatCurrency() {
    return this.currencyPipe.transform(this.price, 'USD', true);
  }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { CurrencyPipe } from '@angular/common';

@NgModule({
  imports: [BrowserModule, FormsModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [CurrencyPipe],
})
export class AppModule {}

Percent Pipe

<h1>Percent Pipe Example</h1>
<p>{{ percentage | percent }}</p>
import { PercentPipe } from '@angular/common';
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  percentage = 0.5;

  constructor(private percentPipe: PercentPipe) {}

  formatPercentage() {
    return this.percentPipe.transform(this.percentage, '2');
  }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
import { PercentPipe } from '@angular/common';

@NgModule({
  imports: [BrowserModule, FormsModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [PercentPipe],
})
export class AppModule {}

Slice Pipe

<p>{{ ['apple', 'banana', 'orange', 'mango'] | slice:1:3 }}</p>

Decimal/number Pipe

<p>{{ 123456.78 | number:'3.2-3' }}</p>

JSON Pipe

<p>{{data | json}}</p>

Async Pipe

async pipe is a built-in feature that provides an easy way to handle asynchronous data streams directly in templates. It is used to subscribe to and automatically unwrap the result of an asynchronous operation, such as an Observable or Promise, in a template.

<p>{{data$ | async}}</p>
// DataService.service.ts
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';

@Injectable()
export class DataService {
  private data$: Observable<string>;

  constructor() {
    // Simulating an asynchronous data source
    this.data$ = of('Hello, async pipe!').pipe(
      // Simulating delay
      delay(2000)
    );
  }

  getData(): Observable<string> {
    return this.data$;
  }
}
// ExampleComponent.component.ts
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { DataService } from './data.service';

@Component({
  selector: 'app-example',
  template: '<div>{{ data$ | async }}</div>',
})
export class ExampleComponent {
  data$: Observable<string>;

  constructor(private dataService: DataService) {
    this.data$ = this.dataService.getData();
  }
}

Back to top⤴️

Decorators

Decorators are design patterns used to isolate the modification or decoration of a class without modifying the source code.

Input

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
  @Input() message: string;
  constructor() { }

  ngOnInit() {
    
  }

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

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],
})
export class ParentComponent implements OnInit {
  parentMessage = 'Hello from the parent component!';
  constructor() {}

  ngOnInit() {}
}
<p>{{ message }}</p>
<app-child [message]="parentMessage"></app-child>
<h1>@Input Example</h1>
<app-parent></app-parent>
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { RouterModule } from '@angular/router';
import { ChildComponent } from './child/child.component';
import { ParentComponent } from './parent/parent.component';

@NgModule({
  imports: [BrowserModule, FormsModule, RouterModule],
  declarations: [AppComponent, ChildComponent, ParentComponent],
  bootstrap: [AppComponent],
})
export class AppModule {}

Output

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
})
export class ChildComponent implements OnInit {
  @Output() messageEvent = new EventEmitter<string>();

  constructor() {}

  ngOnInit() {}

  sendMessage() {
    this.messageEvent.emit('Hello from the child component!');
  }
}
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],
})
export class ParentComponent implements OnInit {
  constructor() {}

  ngOnInit() {}

  handleMessage(message: string) {
    console.log(message);
  }
}
<button (click)="sendMessage()">Send message</button>
<app-child (messageEvent)="handleMessage($event)"></app-child>
<h1>@Output Decorator Example</h1>
<app-parent></app-parent>

HostListener

<h1>@HostListener Decorator Example</h1>
<p>Click the host element to trigger the 'click' event.</p>
import { Component, HostListener } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  @HostListener('click')
  onClick() {
    console.log('The host element was clicked!');
  }
}

contentChild & contentChildren

import {
  Component,
  ContentChild,
  ContentChildren,
  ElementRef,
  OnInit,
  QueryList,
} from '@angular/core';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],
})
export class ParentComponent implements OnInit {
  @ContentChild('childButton1', { static: true }) childButton1: ElementRef;
  @ContentChildren('childButton2') childButtons2: QueryList<ElementRef>;

  ngAfterContentInit() {
    console.log(this.childButton1.nativeElement.textContent);
    this.childButtons2.forEach((button) => {
      console.log(button.nativeElement.textContent);
    });
  }

  constructor() {}

  ngOnInit() {}
}
<ng-content></ng-content>
<h1>@ContentChild Decorator Example</h1>
<app-parent></app-parent>

viewChild & viewChildren

import { Component, ElementRef, QueryList, ViewChild, ViewChildren } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  @ViewChild('childButton1', { static: true }) childButton1: ElementRef;
  @ViewChildren('childButton2') childButtons2: QueryList<ElementRef>;

  ngAfterViewInit() {
    console.log(this.childButton1.nativeElement.textContent);
    this.childButtons2.forEach(button => {
      console.log(button.nativeElement.textContent);
    });
  }
}
<h1>@viewChild & @viewChildren Example</h1>
<button #childButton1>Button 1</button>
<button #childButton2>Button 2</button>

Back to top⤴️

Life Cycle Hooks

OnChanges

It is called when any data-bound property of a directive or component changes.

<form>
  <input [(ngModel)]="message" name="message" />
  <button type="submit" (click)="onSubmit()">Submit</button>
</form>
<p>{{ message }}</p>
import {
  Component,
  Input,
  OnChanges,
  OnInit,
  SimpleChanges,
} from '@angular/core';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css'],
})
export class TestComponent implements OnChanges {
  @Input() message: string;
  prevMessage: string;

  ngOnChanges(changes: SimpleChanges) {
    if (changes.message) {
      console.log(
        `message changed from ${changes.message.previousValue} to ${changes.message.currentValue}`
      );
    }
  }

  onSubmit() {
    this.prevMessage = this.message;
  }
}
<app-test  [message]="'Hello World'"></app-test>

Stackblitz Link

OnInit

It is called after a component has been initialized and its data-bound properties have been checked for the first time.

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  constructor() {}

  ngOnInit() {
    console.log('logged from ngOnInit');
  }
}

Stackblits Link

DoCheck

It is called during every change detection cycle. It allows a component to detect and act upon changes that Angular can't detect on its own.

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements DoCheck {
  ngDoCheck() {
    console.log('ngDoCheck Called');
  }
}

Stackblitz Link

AfterViewInit

It is called after app has fully initialized a component's view.

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterViewInit{
  
  ngAfterViewInit(){
    console.log("after view init")
  }
  clickMe(){
    console.log("link clicked")
  }
}
<a (click)="clickMe()">Click me</a>

Stackblitz Link

AfterViewChecked

It is called after the default change detector has completed checking a component's view for changes.

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterViewChecked {
  ngAfterViewChecked(){
    console.log("after view checked")
  }
  clickMe(){
    console.log("link clicked")
  }
}
<a (click)="clickMe()">Click me</a>

Stackblitz Link

AfterContentInit

It is called after Angular has fully initialized all content of a directive.

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterContentInit {
  ngAfterContentInit() {
    console.log('after content init');
  }
  clickMe() {
    console.log('clicked');
  }
}
<a (click)="clickMe()">Click me</a>

Stackblitz Link

AfterContentChecked

It is called after the default change detector has completed checking all content of a directive.

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterContentInit {
  ngAfterContentChecked() {
    console.log('after content init');
  }
  clickMe() {
    console.log('clicked');
  }
}
<a (click)="clickMe()">Click me</a>

Stackblitz Link

OnDestroy

It is called just before a component or directive is destroyed. It is a good place to clean up any subscriptions or detach any event handlers to avoid memory leaks.

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { of } from 'rxjs';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit, OnDestroy {
  private subscription: Subscription;

  ngOnInit() {
    const someObservable = of(1, 2, 3);
    this.subscription = someObservable.subscribe((data) => {
      console.log(data);
    });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

Stackblitz Link

Back to top⤴️

Forms

Template Driven Form

<form (ngSubmit)="onSubmit()" #form="ngForm">
    <input [(ngModel)]="name" name="name" required>
    <button type="submit">Submit</button>
</form>

Example

<!-- form template -->
<form (ngSubmit)="onSubmit(form)" #form="ngForm">
  <label>
    Name:
    <input type="text" [(ngModel)]="name" name="name" required>
  </label>
  <br>
  <label>
    Email:
    <input type="email" [(ngModel)]="email" name="email" required>
  </label>
  <br>
  <button type="submit" [disabled]="!form.valid">Submit</button>
</form>
import { Component } from '@angular/core';
import { NgForm } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  name: string;
  email: string;

  onSubmit(form: NgForm) {
    console.log(form.value); // { name: 'your name', email: 'your email' }
    console.log(form.valid); // true
  }
}

Reactive Form

Basic Form Control

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    // other imports ...
    ReactiveFormsModule
  ],
})
export class AppModule { }
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';

@Component({
  selector: 'app-name-editor',
  templateUrl: './name-editor.component.html',
  styleUrls: ['./name-editor.component.css']
})
export class NameEditorComponent {
  name = new FormControl('');
}
<label for="name">Name: </label>
<input id="name" type="text" [formControl]="name">

To display form control values

{{ name.value }}

To replace the form control value

<button (click)="update()">Update</button>
update(){
  this.name.setValue('Manthan');
}

Form Group

import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';

@Component({
  selector: 'app-profile-editor',
  templateUrl: './profile-editor.component.html',
  styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
  profileForm = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
  });
}
<form [formGroup]="profileForm" (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>
</form>
<p>Complete the form to enable button.</p>
<button type="submit" [disabled]="!profileForm.valid">Submit</button>

Nested form groups

import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';

@Component({
  selector: 'app-profile-editor',
  templateUrl: './profile-editor.component.html',
  styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
  profileForm = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
    address: new FormGroup({
      street: new FormControl(''),
      city: new FormControl(''),
      state: new FormControl(''),
      zip: new FormControl('')
    })
  });
}
<div formGroupName="address">
  <h2>Address</h2>

  <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>

Form Data

Control State, Validity, and Error Messages

Form and Data Model

FormArrays

Signals

Signals serve as wrappers around values, offering the ability to notify interested consumers whenever the encapsulated value undergoes a change. These signals can accommodate a wide range of values, encompassing both basic primitives and intricate data structures.

Angular Signals

Angular Signals is a powerful system that provides detailed monitoring of state usage within an application, enabling the framework to efficiently optimize rendering updates.

import { Component, OnInit } from '@angular/core';
import { signal } from '@angular/cdk/platform-browser';

 @Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

count = signal(0);

constructor() { }

ngOnInit() {
   this.count.subscribe(value => {
      console.log('Count changed to', value);
   });
}

incrementCount() {
   this.count.value++;
}

}
<h1>Angular Signals Example</h1>

<button (click)="incrementCount()">Increment Count</button>

<p>Count: {{ count }}</p>

Destroy Ref

DestroyRef is a new provider in Angular 16 that allows you to register destroy callbacks for a specific lifecycle scope. This feature is applicable to components, directives, pipes, embedded views, and instances of EnvironmentInjector.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { DestroyRef } from '@angular/core/testing';

@Component({
  selector: 'my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
})
export class MyComponent implements OnInit, OnDestroy {

  constructor(private destroyRef: DestroyRef) {}

  ngOnInit() {
  }

  ngOnDestroy() {
    // Register a destroy callback with the DestroyRef provider.
    this.destroyRef.register(() => {
      // Do any cleanup tasks here.
    });
  }

}

HTTP

Import HttpClient Module in Root Module -

import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
 
@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        HttpClientModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }

Import Required Module in Component/Service -

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

Inject HttpClient service -

constructor(public http: HttpClient) {
}

HTTP GET

getData(){
  return this.http.get('url');
}

HTTP POST

sendData(data: any){
  return this.http.post('url', data);
}

HTTP PUT

updateData(data: any){
  return this.http.put('url', data);
}

HTTP PATCH

updateData(data: any){
  return this.http.patch('url', data);
}

HTTP DELETE

deleteData(id: string){
  return this.http.delete(`url/${id}`);
}

HTTP Interceptor

Http Interceptors are part of @angular/common/http, which inspect and transform HTTP requests from your application to the server and vice-versa on HTTP responses. These interceptors can perform a variety of implicit tasks, from authentication to logging.

Using Observable

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

@Injectable({
  providedIn: 'root'
})

export class MyService {
  constructor(private http: HttpClient) {}

  getData(): Observable<any> {
    return this.http.get<any>('utl');
  }

  sendData(data: any): Observable<any> {
    return this.http.post<any>('utl', data);
  }

  updateData(data: any): Observable<any> {
    return this.http.put<any>('utl', data);
  }

  updateData(data: any): Observable<any> {
    return this.http.patch<any>('utl', data);
  }

  deleteData(id: string): Observable<any> {
    return this.http.delete<any>(`utl/${id}`);
  }
}

Options—Headers/Params

Options—Observe/Response Type

Module

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

@NgModule({
  imports: [BrowserModule, FormsModule, AppRoutingModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Page1Component } from './page-1/page-1.component';
import { Page2Component } from './page-2/page-2.component';

const routes: Routes = [
  { path: 'page-1', component: Page1Component },
  { path: 'page-2', component: Page2Component },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}
<h1>Routing Example</h1>
<a routerLink="page-1">Page-1</a> &nbsp;
<a routerLink="page-2">Page2-</a>
<router-outlet></router-outlet>

Lazy loading

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

@NgModule({
  imports: [BrowserModule, FormsModule, AppRoutingModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  {
    path: 'page-1',
    loadChildren: () =>
      import('./page-1/page-1.module').then((m) => m.Page1Module),
  },
  {
    path: 'page-2',
    loadChildren: () =>
      import('./page-2/page-2.module').then((m) => m.Page2Module),
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Page1Component } from './page-1.component';

const routes: Routes = [
  {
    path: '',
    component: Page1Component,
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class Page1RoutingModule {}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Page1Component } from './page-1.component';
import { Page1RoutingModule } from './page-1-routing.module';

@NgModule({
  imports: [CommonModule, Page1RoutingModule],
  declarations: [Page1Component],
})
export class Page1Module {}
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Page2Component } from './page-2.component';

const routes: Routes = [
  {
    path: '',
    component: Page2Component,
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class Page2RoutingModule {}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Page2Component } from './page-2.component';
import { Page2RoutingModule } from './page-2-routing.module';

@NgModule({
  imports: [CommonModule, Page2RoutingModule],
  declarations: [Page2Component],
})
export class Page2Module {}
<h1>Lazy Loading Example</h1>
<a routerLink="page-1">Page-1</a> &nbsp;
<a routerLink="page-2">Page-2</a>
<router-outlet></router-outlet>

Router

Angular Router is a mechanism in which navigation happens from one view to the next as users perform application tasks. It borrows the concepts or model of browser's application navigation.

Required Route Params

Navigating in app

Optional Route Params

Params

Services & Dependency Injection

Services -

A service is used when a common functionality needs to be provided to various modules. Services allow for greater separation of concerns for your application and better modularity by allowing you to extract common functionality out of components.

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

@Injectable({
  providedIn: 'root'
})
export class SharedService {
  constructor() { }
}

Dependency Injection -

Dependency injection (DI), is an important application design pattern in which a class asks for dependencies from external sources rather than creating them itself.

Routing Module

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule],
  bootstrap: [AppComponent],
})
export class AppModule { }
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CommonModule } from '@angular/common';
 
import { HomeComponent } from './home.component';
 
@NgModule({
  declarations: [HomeComponent],
  imports: [
    CommonModule,
  ],
  providers: [],
})
export class HomeModule { }

Routing Module -

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
 
const routes: Routes = [];
 
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Route Parameters

In Angular, route parameters are used to pass dynamic values in the URL of a route. They allow you to define variable segments in the route path, which can be accessed and used by components and services within your application. Route parameters are denoted by a colon (":") followed by the parameter name.

There are three types of route parameters in Angular:

Path Parameters:

Path parameters are used to define dynamic segments in the URL path. They are specified as part of the route's path and are extracted from the actual URL when navigating to that route. Path parameters are denoted by a colon (":") followed by the parameter name. For example:

{ path: 'users/:id', component: UserComponent }

In this example, ":id" is the path parameter. When navigating to a URL like "/users/123", the value "123" will be extracted and can be accessed in the UserComponent.

Query Parameters:

Query parameters are used to pass additional information in the URL as key-value pairs. They are appended to the URL after a question mark ("?") and can be accessed by components and services. Query parameters are not part of the route path, but they provide additional data to the route. For example:

{ path: 'search', component: SearchComponent }

In this example, a URL like "/search?query=angular" contains a query parameter "query" with the value "angular". The SearchComponent can retrieve the value of the query parameter and use it for searching.

Optional Parameters:

Optional parameters are used when you want to make a route parameter optional. They are denoted by placing a question mark ("?") after the parameter name. Optional parameters can be useful when you have routes with varying parameters. For example:

{ path: 'products/:id/:category?', component: ProductComponent }

In this example, the ":category" parameter is optional. The ProductComponent can be accessed with URLs like "/products/123" or "/products/123/electronics". If the ":category" parameter is present in the URL, it will be available in the component, otherwise, it will be undefined.

Route parameters provide a flexible way to handle dynamic data in your Angular application. They allow you to create routes that can be easily customized and provide a seamless user experience by reflecting the current state of the application in the URL.

Observables in Angular

An observable is a class that can be used to handle asynchronous data streams. Observables are used to handle data that can arrive over time, such as data received from a server, user input, or timed events.

Unsubscribe in Angular

In Angular, managing subscriptions is crucial to avoid memory leaks and improve the performance of your application. Here are five ways to unsubscribe in Angular:

  1. Using the takeUntil operator:

    • Create a subject to act as a notifier.
    • In your component, create a private property for the subject.
    • Subscribe to observables using the takeUntil operator with the subject as the parameter.
    • Emit a value on the subject when you want to unsubscribe, typically in the ngOnDestroy lifecycle hook.
    • In the ngOnDestroy hook, call complete() on the subject to stop emitting values.
    import { Component, OnDestroy } from '@angular/core';
    import { Subject } from 'rxjs';
    import { takeUntil } from 'rxjs/operators';
    
    @Component({
      selector: 'app-example',
      templateUrl: './example.component.html',
      styleUrls: ['./example.component.css']
    })
    export class ExampleComponent implements OnDestroy {
      private unsubscribe$ = new Subject<void>();
    
      ngOnInit() {
        // Subscribe to an observable
        someObservable.pipe(takeUntil(this.unsubscribe$)).subscribe((data) => {
          // Handle data
        });
      }
    
      ngOnDestroy() {
        this.unsubscribe$.next();
        this.unsubscribe$.complete();
      }
    }
  2. Using the async pipe:

    • In your template, use the async pipe to subscribe to observables directly.
    • Angular automatically handles the subscription and unsubscription for you.
    • Ensure you don't manually subscribe to the observable in your component.
    <div>{{ someObservable$ | async }}</div>
  3. Using the Subscription object:

    • Declare a Subscription property in your component.
    • Assign the subscription to the property when subscribing.
    • In the ngOnDestroy hook, unsubscribe from the subscription.
    import { Component, OnDestroy } from '@angular/core';
    import { Subscription } from 'rxjs';
    
    @Component({
      selector: 'app-example',
      templateUrl: './example.component.html',
      styleUrls: ['./example.component.css']
    })
    export class ExampleComponent implements OnDestroy {
      private subscription: Subscription;
    
      ngOnInit() {
        // Assign the subscription
        this.subscription = someObservable.subscribe((data) => {
          // Handle data
        });
      }
    
      ngOnDestroy() {
        // Unsubscribe from the subscription
        this.subscription.unsubscribe();
      }
    }
  4. Using the unsubscribe operator:

    • Store the subscription in a variable.
    • Call the unsubscribe method on the subscription in the ngOnDestroy hook.
    import { Component, OnDestroy } from '@angular/core';
    
    @Component({
      selector: 'app-example',
      templateUrl: './example.component.html',
      styleUrls: ['./example.component.css']
    })
    export class ExampleComponent implements OnDestroy {
      private subscription;
    
      ngOnInit() {
        // Assign the subscription
        this.subscription = someObservable.subscribe((data) => {
          // Handle data
        });
      }
    
      ngOnDestroy() {
        // Unsubscribe from the subscription
        this.subscription.unsubscribe();
      }
    }
  5. Using the ngOnDestroy hook and manual unsubscription:

    • Declare an array to store all the subscriptions.
    • Push the subscription to the array when subscribing.
    • Loop through the array in the ngOnDestroy hook and unsubscribe from each subscription.
    import { Component, OnDestroy } from '@angular/core';
    import { Subscription } from 'rxjs';
    
    @Component({
      selector: 'app-example',
      templateUrl: './example.component.html',
      styleUrls: ['./example.component.css']
    })
    export class ExampleComponent implements OnDestroy {
      private subscriptions: Subscription[] = [];
    
      ngOnInit() {
        // Push the subscription to the array
        this.subscriptions.push(someObservable.subscribe((data) => {
          // Handle data
        }));
      }
    
      ngOnDestroy() {
        // Unsubscribe from all subscriptions
        this.subscriptions.forEach(subscription => subscription.unsubscribe());
      }
    }

Renderer2

Renderer2 is a utility class that provides methods to manipulate and interact with the DOM (Document Object Model). It is used to perform operations such as creating, modifying, and removing elements, applying styles, and listening to events.

import { Component, Renderer2, ElementRef } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `
    <button (click)="changeColor()">Change Color</button>
  `
})
export class ExampleComponent {
  constructor(private renderer: Renderer2, private el: ElementRef) { }

  changeColor() {
    const button = this.el.nativeElement.querySelector('button');
    this.renderer.setStyle(button, 'background-color', 'red');
  }
}

Standalone Components

A standalone component is a type of component which is not part of any Angular module. It provides a simplified way to build Angular applications.

JIT

Just-in-Time (JIT) is a type of compilation that compiles your app in the browser at runtime.

Advantages of AOT

  • Faster startup times as the browser only needs to execute the compiled code.
  • Improved performance due to optimized and pre-compiled templates.
  • Better security as the templates are already compiled and validated before deployment.
  • Smaller bundle sizes since the templates are not included.

AOT

Ahead-of-Time (AOT) is a type of compilation that compiles your app at build time.

Advantages of JIT

  • Faster development cycle as changes can be seen immediately.
  • No build step required during development.
  • More flexible for dynamic template generation.

JIT vs AOT

Differences between AOT and JIT

Feature AOT JIT
Compilation time Build time Runtime
Application size Smaller Larger
Application load time Faster Slower
Debugging More difficult Easier
Development More difficult Easier

Route Guards

CanActivate

import { Injectable } from '@angular/core';
import {
  CanActivate,
  ActivatedRouteSnapshot,
  RouterStateSnapshot,
} from '@angular/router';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {
    return false;
  }
}

CanDeactivate

Resolve

CanLoad

CanActivateChild

API/Server Calls and CORS

Different Environments

Caching

Production Build

Base Href

ng-container - A special element that can hold structural directives without adding new elements to the DOM.

<ng-container>
  ......
</ng-container>

Angular Universal

Angular Universal is a server-side rendering module for Angular applications in various scenarios. This is a community driven project and available under @angular/platform-server package.

// create the application
ng add @nguniversal/express-engine

//run the application
npm run dev:ssr

Angular Animations

Angular's animation system is built on CSS functionality in order to animate any property that the browser considers animatable. These properties includes positions, sizes, transforms, colors, borders etc. The Angular modules for animations are @angular/animations and @angular/platform-browser.

Meta tags

Title Service

import { BrowserModule, Title } from '@angular/platform-browser';
import { BrowserModule, Title } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [Title],
  bootstrap: [AppComponent]
})
export class AppModule { }
export class TitleComponent implements OnInit {
  constructor(private title:Title) { }
}
ngOnInit() {
  this.title.setTitle("Learn Angular")
}
import { Component, OnInit } from '@angular/core';
import { Title, MetaDefinition } from '@angular/platform-browser';
 
@Component({
  template: `<h1>App Component</h1>`
})
export class AppComponent implements OnInit {
  title = 'App Component';
 
  constructor(private title:Title){
  }
 
  ngOnInit() {
    this.title.setTitle("Learn Angular")
  }
 
}

Title Service Example

// app.module.ts
import { BrowserModule, Title } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
 
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home.component';
 
@NgModule({
  declarations: [
    AppComponent, HomeComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [Title],
  bootstrap: [AppComponent]
})
export class AppModule { }
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home.component';

const routes: Routes = [
  {path: 'home', component:HomeComponent},
];
 
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
// app.component.ts
import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Title Service Example';
 
  constructor(private titleService:Title) {
  }
 
  ngOnInit() {
    this.titleService.setTitle(this.title);
  }
}
<!-- app.component.html -->
<h1>Title Service Example</h1>
 
<ul>
  <li><a [routerLink]="['/home']">Home</a> </li>
</ul>
 
<router-outlet></router-outlet>
// home.component.ts
import { Component, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';

@Component({
  template: `<h1>Home Component</h1>`
})
export class HomeComponent implements OnInit {
  title = 'Home Component Title';
 
  constructor(private titleService:Title){
  }
 
  ngOnInit() {
    this.titleService.setTitle(this.title);
  }
 
}

Dynamic Title

// app.module.ts
import { BrowserModule, Title } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
 
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home.component';
 
@NgModule({
  declarations: [
    AppComponent, HomeComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [Title],
  bootstrap: [AppComponent]
})
export class AppModule { }
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home.component';
import { PParentComponent } from './parent.component';
import { ChildComponent } from './child.component';

const routes: Routes = [
  {path: '', component:HomeComponent, data : {title:'Title for Home Component'}},
  {path: 'parent', component:ParentComponent, data : {title:'Title for Parent Component'},
    children: [
      { path: 'child', component:ChildComponent, data : {title:'Title for Child Component'}}
    ]
  },
];
 
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
// app.component.ts
import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { filter, map } from 'rxjs/operators';
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

 constructor(
  private router: Router,
  private activatedRoute: ActivatedRoute,
  private titleService: Title
  ) { }
 
  ngOnInit() {
 
    this.router.events.pipe(
        filter(event => event instanceof NavigationEnd),
      )
      .subscribe(() => {
 
        var rt = this.getChild(this.activatedRoute)
 
        rt.data.subscribe(data => {
          console.log(data);
          this.titleService.setTitle(data.title)})
      })
 
  }
 
  getChild(activatedRoute: ActivatedRoute) {
    if (activatedRoute.firstChild) {
      return this.getChild(activatedRoute.firstChild);
    } else {
      return activatedRoute;
    }
 
  }
}
<!-- app.component.html -->
<h1>Dynamic Title Example</h1>
 
<ul>
  <li><a routerLink="">Home</a> </li>
  <li><a [routerLink]="['/parent']">Parent</a> </li>
  <li><a [routerLink]="['/child']">Child</a> </li>
</ul>
 
<router-outlet></router-outlet>
// home.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  template: `<h1>Home Component</h1>`
})
export class HomeComponent implements OnInit {
 
  constructor(){
  }
 
  ngOnInit() {
  }
 
}
// parent.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  template: `<h1>Parent Component</h1>
  <router-outlet></router-outlet>
  `
})
export class ParentComponent implements OnInit {
 
  constructor(){
  }
 
  ngOnInit() {
  }
 
}
// child.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  template: `<h1>Child Component</h1>`
})
export class ChildComponent implements OnInit {
 
  constructor(){
  }
 
  ngOnInit() {
  }
 
}

Meta Service

import { BrowserModule, Meta } from '@angular/platform-browser';
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [Meta],
  bootstrap: [AppComponent]
})
export class AppModule { }
import { Component, OnInit } from '@angular/core';
import { Meta, MetaDefinition } from '@angular/platform-browser';
 
@Component({
  template: `<h1>App Component</h1>`
})
export class AppComponent implements OnInit {
  title = 'App Component';
 
  constructor(private metaService:Meta){
  }
 
  ngOnInit() {
    this.metaService.addTag( { name:'description',content:"Article Description"});
  }
 
}

Adding Tags with addTag() & addTags()

this.metaService.addTag( { name:'description',content:"Article Description"});
this.metaService.addTag( 
  { name: 'description', content: 'Article Description' },
  { name: 'robots', content: 'index,follow' },
  { property: 'og:title', content: 'Content Title for social media' }
);

Reading the Tags with getTag()

this.metaService.getTag("name='description'")

Update the Tag with updateTag()

this.metaService.updateTag( { name:'robots', content:'index, nofoloow'},"name='robots'");

Removing the Tag with removeTag()

this.metaService.removeTag("name='robots'");

Deploying an Angular Application

DEPLOYMENT TO PACKAGE
Firebase hosting @angular/fire
Vercel vercel init angular
Netlify @netlify-builder/deploy
GitHub pages angular-cli-ghpages
NPM ngx-deploy-npm
Amazon Cloud S3 @jefiozie/ngx-aws-deploy

CLI Commands

Installing Angular CLI

npm install -g @angular/cli

Help

ng help

Check version

ng version

Create, build, and serve a new, basic Angular project cli command

ng new my-first-project
cd my-first-project
ng serve

Generating new application

ng new app-name

Create new app without installing cli

npm init @angular app-name

Component

ng g c component-name
ng generate component component-name

Adding External libraries

ng add

Build

ng build

Running project

ng serve

Run project on particular port

ng serve --port=portname
// example
ng serve --port=3000

Run project and open the url in default browser

ng  serve --open

Update

ng update

Directive

ng generate directive component-name
ng g directive component-name

Module

ng generate module module-name
ng g m module-name

Service

ng generate service component-name
ng g service component-name

Routing Module

ng g module module-name --routing
ng g m module-name --routing

Component with module, routing module

ng generate module component-name --route component-name --module app.module

Pipe

ng g pipe pipe-name

Enum

ng g enum some-enum

Class

ng g cl my-class

Interface

ng g interface my-interface

Guard

ng g guard guard-name

Multiple Projects in one Angular App

ng generate application sub-app-name

ng new app-name --create-application=false

Generate environments

ng generate environments

Version compatibility

ANGULAR NODE.JS TYPESCRIPT RXJS
16.1.x ^16.14.0 and ^18.10.0 >=4.9.3 <5.2.0 ^6.5.3 and ^7.4.0
16.0.x ^16.14.0 and ^18.10.0 >=4.9.3 <5.1.0 ^6.5.3 and ^7.4.0
15.1.x and 15.2.x ^14.20.0 and ^16.13.0 and ^18.10.0 >=4.8.2 <5.0.0 ^6.5.3 and ^7.4.0
15.0.x ^14.20.0 and ^16.13.0 and ^18.10.0 ~4.8.2 ^6.5.3 and ^7.4.0
14.2.x and 14.3.x ^14.15.0 and ^16.10.0 >=4.6.2 <4.9.0 ^6.5.3 and ^7.4.0
14.0.x and 14.1.x ^14.15.0 and ^16.10.0 >=4.6.2 <4.8.0 ^6.5.3 and ^7.4.0

Imports

Angular

import { Component } from '@angular/core';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { CommonModule } from '@angular/common';
import { NgModel } from '@angular/forms';
import { NgForm } from '@angular/forms';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { ActivatedRoute } from '@angular/router';
import { Router } from '@angular/router';

Angular Material

import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatIconModule } from '@angular/material/icon';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatMenuModule } from '@angular/material/menu';
import { MatSelectModule } from '@angular/material/select';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatNativeDateModule } from '@angular/material/core';
import { MatCardModule } from '@angular/material/card';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatRadioModule } from '@angular/material/radio';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatTabsModule } from '@angular/material/tabs';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatAutocompleteModule } from '@angular/material/autocomplete';

RxJS

import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { AsyncSubject } from 'rxjs/AsyncSubject';
import { Subscription } from 'rxjs/Subscription';
import { from } from 'rxjs';
import { fromEvent } from 'rxjs';
import { interval } from 'rxjs';
import { timer } from 'rxjs';
import { merge } from 'rxjs';
import { zip } from 'rxjs';
import { combineLatest } from 'rxjs';
import { concat } from 'rxjs';
import { forkJoin } from 'rxjs';
import { race } from 'rxjs';
import { map } from 'rxjs/operators';
import { filter } from 'rxjs/operators';
import { reduce } from 'rxjs/operators';
import { tap } from 'rxjs/operators';
import { catchError } from 'rxjs/operators';
import { retry } from 'rxjs/operators';
import { switchMap } from 'rxjs/operators';
import { take } from 'rxjs/operators';
import { debounceTime } from 'rxjs/operators';
import { distinctUntilChanged } from 'rxjs/operators';
// and many more...

Firebase

import { AngularFireModule } from "@angular/fire/compat";
import { AngularFireAuthModule } from "@angular/fire/compat/auth";
import { AngularFireStorageModule } from '@angular/fire/compat/storage';
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
import { AngularFireDatabaseModule } from '@angular/fire/compat/database';
import { AngularFireStorage } from '@angular/fire/storage';

import { AngularFireModule } from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { AngularFireDatabaseModule } from '@angular/fire/database';
import { AngularFireStorageModule } from '@angular/fire/storage';
import { AngularFirestoreModule } from '@angular/fire/firestore';
import { AngularFireFunctionsModule } from '@angular/fire/functions';
import { AngularFireMessagingModule } from '@angular/fire/messaging';

TypeScript

TypeScript is JavaScript with syntax for types.

Rxjs

Reactive Extensions Library for JavaScript - RxJS is a library for reactive programming using Observables, to make it easier to compose asynchronous or callback-based code.

NgRx

NgRx is a Reactive libraries for Angular,

Learn more from GitHub Repositories

Learn more from Websites

Learn more from Books

Learn from YouTube Channels

Learn More From Blogs Sites

List of Online Editors/Compiler

List of Twitter Users

List of LinkedIn Users

🙏🏻Please Support and Don't Forget to give star⭐, Also Feel free to contribute

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment