Skip to main content

🅰️ Angular Framework Overview

Angular is Google's opinionated, batteries-included framework for building large single-page applications in TypeScript. Where React is a library you assemble and Vue is a progressive framework you grow into, Angular hands you the whole toolkit on day one — routing, forms, HTTP, testing, and a strict architecture — so big teams can move together without reinventing the plumbing.

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Explain how modern Angular differs from AngularJS and why the 2016 rewrite mattered
  • Identify Angular's core building blocks — components, services, directives, and pipes
  • Describe the roles of TypeScript, dependency injection, and RxJS in an Angular app
  • Scaffold and run a project with the Angular CLI and read its project structure
  • Decide when Angular is the right choice versus React or Vue

Estimated Time: 35–45 minutes  •  Difficulty: Intermediate

Hands-on: Scaffold a new Angular app with the CLI and add your first standalone component.

In This Lesson

What Is Angular?

Angular is a comprehensive framework for building client-side single-page applications (SPAs) with HTML, CSS, and TypeScript. It is maintained by Google and used at scale by enterprises that value consistency and long-term maintainability over maximum flexibility.

💡 The framework-vs-library distinction: A library (like React) does one job and lets you pick everything else — router, data fetching, forms. A framework (like Angular) makes those decisions for you and provides them in the box. The trade-off is opinion for convenience: you write less glue code, but you follow Angular's way of doing things.

Because Angular ships a router, an HTTP client, a forms system, a dependency-injection container, and a testing harness together, two Angular projects at two different companies look remarkably alike. That familiarity is Angular's superpower on large teams: a developer can move between codebases and be productive quickly.

📖 Key Terms

SPA (Single-Page Application): a web app that loads once and updates the view with JavaScript instead of requesting whole new pages from the server.

Opinionated: the framework prescribes a preferred structure and patterns rather than leaving them to you.

TypeScript: a typed superset of JavaScript that compiles to plain JS, catching type errors before the code ever runs.

A Short History

Knowing the timeline saves you from a common confusion: "AngularJS" and "Angular" are two different things.

EraYearWhat changed
AngularJS (1.x)2010A JavaScript framework that popularized two-way data binding and MVC in the browser. Now end-of-life.
Angular 22016A complete rewrite in TypeScript with a component-based architecture — a clean break, not an upgrade.
Angular 4+2017+Semantic versioning with a major release roughly every six months (version 3 was skipped to align package numbers).
Modern Angular (16–19)2023–2025Standalone components (no NgModule required), the new control-flow syntax (@if/@for), and signals for fine-grained reactivity.
flowchart LR A[AngularJS 1.x
2010] -->|Complete rewrite
in TypeScript| B[Angular 2
2016] B -->|Semantic versioning| C[Angular 4–15] C -->|Standalone + signals| D[Modern Angular
16–19+]

⚠️ "Angular" means Angular 2+

When people say "Angular" today they mean the modern, TypeScript-based framework — not AngularJS. Avoid old tutorials that use $scope, ng-controller, or angular.module(); those are AngularJS and no longer relevant.

An analogy: AngularJS was a house built with traditional, on-site carpentry. Modern Angular is the same house built from a standardized, prefabricated system — the result looks similar, but the newer approach gives you consistent parts, better tooling, and a far more predictable build.

The Five Pillars

Five features define the Angular developer experience. Understand these and the rest of the framework falls into place.

1. TypeScript-first

Angular is written in TypeScript and assumes you'll use it too. Strong typing gives you autocomplete, safe refactors, and compile-time error catching — invaluable on codebases with hundreds of files.

2. Component-based architecture

Every screen is a tree of components, each bundling a template, a class of logic, and scoped styles. Components nest and compose, so complex UIs are built from small, testable pieces.

3. Dependency injection (DI)

Angular has a built-in DI container. A component declares what it needs in its constructor and Angular supplies it — which makes services shareable and, crucially, easy to swap for mocks during testing.

4. RxJS & reactivity

Asynchronous data (HTTP responses, user events, timers) flows through Observables from the RxJS library. Newer Angular adds signals for simpler, fine-grained reactive state.

5. A complete toolkit

Router, forms (template-driven and reactive), HttpClient, and testing utilities all ship with the framework — no shopping around for third-party packages to cover the basics.

✅ Why this matters

These pillars are why Angular scales to large teams: strict types prevent whole classes of bugs, DI keeps modules loosely coupled, and a shared toolkit means everyone solves routing, forms, and HTTP the same way.

Core Building Blocks

Four concepts make up almost every Angular app. Here's how they relate: a component renders a template, injects services for data and logic, and uses directives and pipes to shape what appears on screen.

Angular building blocks and how they connect A component sits at the center. It renders a template, injects a service, and applies directives and pipes to transform the view. Component class + template Template HTML + bindings Service data & logic Directive DOM behavior Pipe format data renders injects
Figure 1 — The four building blocks. The component is the hub: it renders a template, pulls data from services, and shapes output with directives and pipes.

Components

A component is a TypeScript class annotated with the @Component decorator. The decorator's metadata connects the class to a template and styles.

// product-list.component.ts
import { Component, OnInit, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Product } from './product.model';
import { ProductService } from './product.service';

@Component({
  selector: 'app-product-list',          // used as <app-product-list> in HTML
  standalone: true,                       // modern Angular: no NgModule needed
  imports: [CommonModule],                // template dependencies
  templateUrl: './product-list.component.html',
  styleUrl: './product-list.component.css',
})
export class ProductListComponent implements OnInit {
  products: Product[] = [];
  selectedProduct: Product | null = null;

  // inject() is the modern alternative to constructor injection
  private productService = inject(ProductService);

  ngOnInit(): void {
    this.productService.getProducts()
      .subscribe(products => (this.products = products));
  }

  selectProduct(product: Product): void {
    this.selectedProduct = product;
  }
}

Templates & data binding

Templates are HTML enhanced with Angular's binding syntax and the new built-in control flow (@if, @for) introduced in Angular 17:

<!-- product-list.component.html -->
<h2>Products</h2>

@if (products.length === 0) {
  <p class="no-data">No products found.</p>
} @else {
  <ul>
    @for (product of products; track product.id) {
      <li [class.selected]="product === selectedProduct"
          (click)="selectProduct(product)">
        <span>{{ product.name }}</span>
        <span>{{ product.price | currency }}</span>
      </li>
    }
  </ul>
}

The bindings are worth memorizing: {{ }} interpolates a value, [prop] binds a property one way, (event) listens for an event, and [(ngModel)] binds two ways. The | currency at the end is a pipe.

Services

Services hold non-UI logic — data fetching, business rules, shared state — and are provided through DI. The providedIn: 'root' option makes a service an app-wide singleton:

// product.service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, catchError, of, tap } from 'rxjs';
import { Product } from './product.model';

@Injectable({ providedIn: 'root' })
export class ProductService {
  private http = inject(HttpClient);
  private productsUrl = '/api/products';

  getProducts(): Observable<Product[]> {
    return this.http.get<Product[]>(this.productsUrl).pipe(
      tap(() => console.log('fetched products')),
      catchError(() => of([])) // keep the app running on error
    );
  }
}

Directives & pipes

Directives attach behavior to elements — ngClass toggles classes, ngStyle sets inline styles, and you can write custom ones. Pipes transform values for display without mutating them: {{ price | currency }}, {{ name | uppercase }}, or a chain like {{ birthday | date:'fullDate' | uppercase }}.

Standalone Components & a First App

Historically every Angular building block had to be declared inside an NgModule — a chunk of configuration boilerplate. Since Angular 15, standalone components are the default: a component declares its own template dependencies via its imports array, and the app boots without a root module.

// main.ts — bootstrapping a standalone app
import { bootstrapApplication } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http';
import { provideRouter } from '@angular/router';
import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';

bootstrapApplication(AppComponent, {
  providers: [
    provideHttpClient(),   // makes HttpClient injectable everywhere
    provideRouter(routes), // registers application routes
  ],
});

Compare that with the older module-based bootstrap, which required a separate AppModule listing every declaration, import, and provider. Standalone components remove that ceremony while keeping the same DI and component model.

💡 Should you still learn NgModules?

You'll meet NgModules in existing codebases, so recognizing them is useful. But for new work, prefer standalone components and the provide* functions — they're the direction Angular is heading.

The Angular CLI

The Angular CLI is the command-line tool that scaffolds projects, runs a dev server, generates code, and builds for production. It enforces consistent structure so you spend time on features, not boilerplate.

# Install the CLI globally (once)
npm install -g @angular/cli

# Create a new project (prompts for routing + stylesheet)
ng new my-angular-app

# Move in and start the dev server with live reload
cd my-angular-app
ng serve --open

# Generate a standalone component and a service
ng generate component dashboard      # shorthand: ng g c dashboard
ng generate service services/data    # shorthand: ng g s services/data

# Build an optimized production bundle
ng build

A freshly generated project has a predictable shape:

my-angular-app/
├── src/
│   ├── app/
│   │   ├── app.component.ts      # root component logic
│   │   ├── app.component.html    # root template
│   │   ├── app.component.css     # root styles
│   │   ├── app.routes.ts         # route definitions
│   │   └── app.config.ts         # app-level providers
│   ├── assets/                   # images, fonts, static files
│   ├── index.html                # single HTML shell
│   ├── main.ts                   # bootstrap entry point
│   └── styles.css                # global styles
├── angular.json                  # CLI/build configuration
├── package.json                  # dependencies & scripts
└── tsconfig.json                 # TypeScript configuration

Terminal output from ng serve

✔ Compiled successfully.
  ➜  Local:   http://localhost:4200/
  ➜  watch mode enabled. Watching for file changes...

Angular vs React vs Vue

These three dominate the frontend world. None is objectively "best"; they make different trade-offs.

AspectAngularReactVue
TypeFull frameworkLibraryProgressive framework
LanguageTypeScript-firstJS or TSJS or TS
Learning curveSteeperModerateGentle
Opinion levelHighly opinionatedFlexibleConventions with flexibility
State managementServices, RxJS, NgRx, signalsContext, Redux, ZustandPinia
ToolingBatteries-included CLIVite / community toolsVite / official CLI

✅ When to choose Angular

  • Large, long-lived enterprise applications with many developers
  • Teams that want a standardized, opinionated structure out of the box
  • Projects that benefit from strong typing and a full built-in toolkit
  • Teams already comfortable with TypeScript

Real-world users include Google (Gmail, Cloud Console), Microsoft (parts of Office 365), Delta Air Lines, and Deutsche Bank.

Hands-on Exercise

🏋️ Scaffold Your First Angular App

Objective: Create a working Angular project and add a standalone component that renders data.

Instructions:

  1. Install the CLI and create a project (choose Yes for routing, CSS for styles):
    npm install -g @angular/cli
    ng new dashboard-app
    cd dashboard-app
  2. Start the dev server: ng serve --open. Confirm the welcome page loads at localhost:4200.
  3. Generate a component: ng g c metric-card.
  4. Give it an @Input() for a title and value, and render them in the template.
  5. Use the component several times in app.component.html with different metrics (e.g. Users, Revenue, Uptime).
💡 Hint

An @Input() lets a parent pass data down: declare @Input() title = ''; in the component class, then use <app-metric-card [title]="'Users'" [value]="1284"></app-metric-card> in the parent template. Remember to add CommonModule to the component's imports if you use pipes or control flow.

✅ Example solution
// metric-card.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-metric-card',
  standalone: true,
  template: `
    <div class="metric-card">
      <h3>{{ title }}</h3>
      <p class="value">{{ value }}</p>
    </div>
  `,
  styles: [`
    .metric-card { border: 1px solid #ccc; border-radius: 8px; padding: 1rem; }
    .value { font-size: 2rem; font-weight: 700; }
  `],
})
export class MetricCardComponent {
  @Input() title = '';
  @Input() value: string | number = '';
}
<!-- app.component.html -->
<app-metric-card [title]="'Users'" [value]="1284"></app-metric-card>
<app-metric-card [title]="'Revenue'" [value]="'$9,410'"></app-metric-card>
<app-metric-card [title]="'Uptime'" [value]="'99.9%'"></app-metric-card>

Don't forget to import MetricCardComponent into AppComponent's imports array so the template can use it.

🎯 Quick Quiz

Question 1: What is the main difference between AngularJS and modern Angular?

Question 2: Which statement best describes a service in Angular?

Question 3: In modern Angular, what do standalone components let you avoid?

Summary & Quiz

🎉 Key Takeaways

  • Angular is Google's opinionated, TypeScript-first framework for large SPAs — a full toolkit, not just a view library.
  • "Angular" means Angular 2+; AngularJS (1.x) is a separate, retired framework.
  • Its five pillars are TypeScript, components, dependency injection, RxJS/signals, and a complete built-in toolkit.
  • Apps are built from components, services, directives, and pipes, scaffolded by the Angular CLI.
  • Modern Angular favors standalone components over NgModules and the new @if/@for control flow.

📚 Further Reading

🚀 What's Next?

Next we'll go deep on the most important building block: the component. You'll learn its anatomy, lifecycle hooks, and every way parents and children can talk to each other.

🎉 Great start!

You now have the map of Angular. Time to zoom into components.