Skip to main content

Documentation Index

Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt

Use this file to discover all available pages before exploring further.

Angular Architecture

Module Overview

Estimated Time: 2-3 hours | Difficulty: Beginner | Prerequisites: HTML, CSS, JavaScript basics
Welcome to Angular! This module covers everything you need to get started with Angular development, from installation to understanding how Angular applications work under the hood. What You’ll Learn:
  • What Angular is and why it’s powerful
  • Setting up your development environment
  • Creating projects with Angular CLI
  • Understanding the project structure
  • TypeScript essentials for Angular
  • How Angular applications bootstrap

What is Angular?

Angular is a platform and framework for building single-page client applications using HTML and TypeScript. Developed and maintained by Google, it is one of the most widely adopted frameworks for enterprise web development — companies like Google (Google Cloud Console, Firebase Console), Microsoft (Office 365, Xbox), Deutsche Bank, and Forbes all run Angular in production. Angular provides:

Complete Solution

Routing, forms, HTTP, testing—everything included out of the box

TypeScript First

Built with TypeScript for better tooling and maintainability

Component-Based

Build UIs from reusable, self-contained components

Enterprise Ready

Scalable architecture for large applications

Angular vs React vs Vue

FeatureAngularReactVue
TypeFull FrameworkLibraryProgressive Framework
LanguageTypeScriptJavaScript/TypeScriptJavaScript/TypeScript
ArchitectureOpinionatedFlexibleFlexible
Learning CurveSteeperModerateGentle
Best ForEnterprise AppsFlexible ProjectsProgressive Adoption
Maintained ByGoogleMetaCommunity

Setting Up Your Environment

Prerequisites

  1. Node.js (version 18.x or higher)
  2. npm (comes with Node.js)
  3. Code Editor (VS Code recommended)
# Check Node.js version
node --version  # Should be 18.x or higher

# Check npm version
npm --version   # Should be 9.x or higher

Installing Angular CLI

The Angular CLI (Command Line Interface) is the official tool for creating, developing, and maintaining Angular applications. Think of it like a Swiss Army knife for Angular development — it scaffolds projects, generates components, runs tests, builds for production, and handles configuration so you can focus on writing features instead of wrestling with tooling.
# Install Angular CLI globally
npm install -g @angular/cli

# Verify installation
ng version
Pro Tip: If you encounter permission errors on macOS/Linux, consider using nvm (Node Version Manager) or prefix with sudo.

VS Code Extensions

Install these extensions for the best Angular development experience:
// Recommended extensions
{
  "recommendations": [
    "angular.ng-template",          // Angular Language Service
    "bradlc.vscode-tailwindcss",    // Tailwind CSS IntelliSense
    "ms-vscode.vscode-typescript-next", // TypeScript
    "esbenp.prettier-vscode",       // Code formatting
    "nrwl.angular-console"          // Nx Console (optional)
  ]
}

Creating Your First Angular App

Generate a New Project

# Create a new Angular project
ng new my-first-app

# Navigate into the project
cd my-first-app

# Start the development server
ng serve
During project creation, you’ll be asked:
  1. Would you like to add Angular routing? → Yes
  2. Which stylesheet format? → CSS, SCSS, Sass, or Less
Recommendation: Choose SCSS for more powerful styling capabilities with variables, nesting, and mixins.

Project Structure

my-first-app/
├── src/
│   ├── app/
│   │   ├── app.component.ts      # Root component
│   │   ├── app.component.html    # Root template
│   │   ├── app.component.scss    # Root styles
│   │   ├── app.component.spec.ts # Root tests
│   │   ├── app.config.ts         # App configuration
│   │   └── app.routes.ts         # Route definitions
│   │
│   ├── assets/                   # Static assets (images, fonts)
│   ├── index.html               # Main HTML file
│   ├── main.ts                  # Application entry point
│   └── styles.scss              # Global styles

├── angular.json                 # Angular CLI configuration
├── package.json                 # Dependencies and scripts
├── tsconfig.json               # TypeScript configuration
└── tsconfig.app.json           # App-specific TS config

Understanding Key Files

main.ts - Application Entry Point

This is the first file that runs when your application starts. It is the equivalent of main() in Java or C — the single entry point that kicks everything off.
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';

// Bootstrap the application with the root component.
// This tells Angular: "Start the app by creating AppComponent
// and rendering it into the <app-root> tag in index.html."
bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));

app.config.ts - Application Configuration

This is where you register application-wide services and features. Think of it as the “settings panel” for your entire app — routing, HTTP, animations, and any global services all get configured here.
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';

import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    // Zone.js change detection with event coalescing enabled.
    // Event coalescing batches multiple DOM events (like rapid clicks)
    // into a single change detection cycle for better performance.
    provideZoneChangeDetection({ eventCoalescing: true }),

    // Register the router with your app's route definitions
    provideRouter(routes),

    // Enable HttpClient for making API calls throughout the app
    provideHttpClient()
  ]
};

app.component.ts - Root Component

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

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {
  title = 'my-first-app';
}

TypeScript Essentials for Angular

Angular is built with TypeScript. Here are the key concepts you need:

Type Annotations

// Basic types
let name: string = 'Angular';
let version: number = 17;
let isAwesome: boolean = true;
let features: string[] = ['Signals', 'Standalone', 'SSR'];

// Object types
interface User {
  id: number;
  name: string;
  email: string;
  role?: string;  // Optional property
}

const user: User = {
  id: 1,
  name: 'John Doe',
  email: 'john@example.com'
};

Classes and Decorators

If you are coming from React or Vue, decorators might be new to you. A decorator is a special annotation (the @ symbol) that attaches metadata to a class, property, or method. Angular reads this metadata at runtime to understand what a class is supposed to do. Think of decorators like name badges at a conference — the badge does not change who you are, but it tells the framework how to treat you.
// Classes with TypeScript
class UserService {
  private users: User[] = [];
  
  // "private http: HttpClient" in the constructor is TypeScript shorthand.
  // It declares a private property AND assigns the injected value in one step.
  constructor(private http: HttpClient) {}
  
  getUsers(): Observable<User[]> {
    return this.http.get<User[]>('/api/users');
  }
}

// Decorators (heavily used in Angular)
@Component({
  selector: 'app-user',        // The HTML tag name for this component
  template: '<h1>{{ user.name }}</h1>'
})
export class UserComponent {
  @Input() user!: User;                    // Data coming IN from a parent component
  @Output() selected = new EventEmitter<User>(); // Events going OUT to a parent
}

Generics

// Generic function
function wrapInArray<T>(value: T): T[] {
  return [value];
}

// Generic interface
interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

// Usage
const response: ApiResponse<User[]> = {
  data: [{ id: 1, name: 'John', email: 'john@example.com' }],
  status: 200,
  message: 'Success'
};

Angular CLI Commands

The CLI provides many useful commands:
# Development server
ng serve                    # Start dev server at localhost:4200
ng serve --port 3000       # Use custom port
ng serve --open            # Open browser automatically

# Generate code
ng generate component user  # or: ng g c user
ng generate service data   # or: ng g s data
ng generate pipe currency  # or: ng g p currency
ng generate directive highlight  # or: ng g d highlight
ng generate guard auth     # or: ng g g auth

# Build
ng build                   # Development build
ng build --configuration production  # Production build

# Testing
ng test                    # Run unit tests
ng e2e                     # Run end-to-end tests

# Linting
ng lint                    # Lint your code

Component Generation Options

# Generate a component with inline template and styles
ng g c user --inline-template --inline-style

# Generate without test file
ng g c user --skip-tests

# Generate in a specific directory
ng g c features/user/user-profile

# Flat (no folder)
ng g c shared/button --flat

How Angular Apps Bootstrap

Understanding the bootstrap process helps you debug issues and configure your app correctly. When something goes wrong at startup — a blank screen, a “missing provider” error, or a component that does not render — knowing this sequence tells you exactly where to look.
Practical tip: If you see a blank page with no errors in the console, the issue is almost always in step 3-6. Check that your AppComponent selector matches the tag in index.html, and that appConfig has all required providers.
┌─────────────────────────────────────────────────────────────────────────┐
│                    Angular Bootstrap Process                             │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   1. Browser loads index.html                                            │
│         │                                                                │
│         ▼                                                                │
│   2. index.html loads main.ts via <script>                              │
│         │                                                                │
│         ▼                                                                │
│   3. main.ts calls bootstrapApplication(AppComponent, appConfig)        │
│         │                                                                │
│         ▼                                                                │
│   4. Angular creates the root injector with providers from appConfig    │
│         │                                                                │
│         ▼                                                                │
│   5. Angular instantiates AppComponent                                   │
│         │                                                                │
│         ▼                                                                │
│   6. Angular renders AppComponent's template into <app-root>            │
│         │                                                                │
│         ▼                                                                │
│   7. Zone.js starts monitoring for async events                         │
│         │                                                                │
│         ▼                                                                │
│   8. Application is ready for user interaction!                          │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>MyFirstApp</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <!-- Angular will render AppComponent here -->
  <app-root></app-root>
</body>
</html>

Your First Component

Let’s create a simple component to understand the basics:
ng generate component hello-world
This creates:
src/app/hello-world/
├── hello-world.component.ts
├── hello-world.component.html
├── hello-world.component.scss
└── hello-world.component.spec.ts

Component Code

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

@Component({
  selector: 'app-hello-world',
  standalone: true,
  imports: [],
  templateUrl: './hello-world.component.html',
  styleUrl: './hello-world.component.scss'
})
export class HelloWorldComponent {
  name = 'Angular';
  
  greet() {
    alert(`Hello from ${this.name}!`);
  }
}
<!-- hello-world.component.html -->
<div class="greeting">
  <h1>Hello, {{ name }}!</h1>
  <p>Welcome to your first Angular component.</p>
  <button (click)="greet()">Say Hello</button>
</div>
/* hello-world.component.scss */
.greeting {
  padding: 2rem;
  text-align: center;
  
  h1 {
    color: #DD0031;
  }
  
  button {
    background: #DD0031;
    color: white;
    border: none;
    padding: 0.5rem 1rem;
    border-radius: 4px;
    cursor: pointer;
    
    &:hover {
      background: #C3002F;
    }
  }
}

Using the Component

// app.component.ts
import { Component } from '@angular/core';
import { HelloWorldComponent } from './hello-world/hello-world.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [HelloWorldComponent],  // Import the component
  template: `
    <main>
      <app-hello-world></app-hello-world>
    </main>
  `
})
export class AppComponent {}

Angular DevTools

Install the Angular DevTools browser extension for debugging:
  1. Install from Chrome Web Store or Firefox Add-ons
  2. Open Chrome DevTools (F12)
  3. Look for the “Angular” tab
Tip: Angular DevTools only works with development builds. Production builds have debugging disabled.

DevTools Features

  • Component Explorer: Inspect component tree and properties
  • Profiler: Analyze change detection performance
  • Router: Debug routing state

Practice Exercise

Exercise: Create a Counter App

Create a simple counter application with:
  1. A display showing the current count
  2. Increment button (+)
  3. Decrement button (-)
  4. Reset button
Bonus: Add a maximum value of 10 and minimum of 0
// counter.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-counter',
  standalone: true,
  template: `
    <div class="counter">
      <h2>Count: {{ count }}</h2>
      <div class="buttons">
        <button (click)="decrement()" [disabled]="count <= 0">-</button>
        <button (click)="reset()">Reset</button>
        <button (click)="increment()" [disabled]="count >= 10">+</button>
      </div>
    </div>
  `,
  styles: [`
    .counter {
      text-align: center;
      padding: 2rem;
    }
    .buttons {
      display: flex;
      gap: 1rem;
      justify-content: center;
    }
    button {
      padding: 0.5rem 1rem;
      font-size: 1.2rem;
      cursor: pointer;
    }
    button:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
  `]
})
export class CounterComponent {
  count = 0;
  
  increment() {
    if (this.count < 10) {
      this.count++;
    }
  }
  
  decrement() {
    if (this.count > 0) {
      this.count--;
    }
  }
  
  reset() {
    this.count = 0;
  }
}

Summary

In this module, you learned:
1

What Angular Is

A complete platform for building web applications maintained by Google
2

Environment Setup

How to install Node.js, Angular CLI, and configure VS Code
3

Project Creation

Using ng new to scaffold projects and understanding the file structure
4

TypeScript Essentials

Types, interfaces, classes, and decorators used in Angular
5

Bootstrap Process

How Angular applications start and render components

Interview Deep-Dive

Strong Answer: Zone.js monkey-patches every asynchronous browser API — setTimeout, setInterval, Promise.then, addEventListener, XMLHttpRequest, fetch — and wraps them in “zones.” When any async operation completes inside Angular’s zone, Zone.js notifies Angular’s change detection to run a check from the root component down. This is why Angular “magically” updates the view when an HTTP response arrives or a timeout fires — Zone.js is the mechanism that triggers the check.If you removed Zone.js, Angular would have no way to know when async operations complete, so templates would never update automatically. You would need to manually call ChangeDetectorRef.detectChanges() or markForCheck() after every async operation. Starting with Angular 18, provideExperimentalZonelessChangeDetection() enables exactly this scenario — but it requires you to use signals for all template-bound state, because signals have their own notification mechanism that does not depend on Zone.js. The benefit is roughly 15KB less bundle size and no unexpected change detection triggered by third-party libraries.Follow-up: Can you describe a scenario where Zone.js causes a performance problem? Answer: A common one is third-party charting libraries like D3 or Chart.js. These libraries use requestAnimationFrame and mousemove handlers internally, which Zone.js intercepts and triggers change detection on. If you have a chart with 60fps animations, Angular runs change detection 60 times per second across your entire component tree — even though none of your Angular data changed. The fix is to run the chart initialization inside NgZone.runOutsideAngular(), which tells Zone.js to ignore async operations in that callback.
Strong Answer: The constructor runs during class instantiation, before Angular has set any inputs or rendered any template. It is the right place for pure dependency injection setup — assigning injected services to class properties (though inject() now handles this declaratively). The constructor should never access @Input values because they have not been set yet.ngOnInit runs after Angular has set the initial input bindings and the component is fully wired up. This is the right place for initialization logic that depends on input values — fetching data based on a route parameter, setting up subscriptions that read from inputs, or any logic that needs the component to be “ready.”The common mistake is calling inject() in ngOnInit — that actually fails because inject() only works during the injection context (constructor or field initializer). So the practical rule is: use inject() for DI in field declarations, use ngOnInit for initialization logic that depends on inputs. Putting everything in ngOnInit is not technically wrong, but putting DI-dependent setup logic in the constructor is — because the component is not fully initialized yet.Follow-up: What about the new signal-based inputs? Does this change the ngOnInit pattern? Answer: With signal inputs (input.required, input()), the value is available as a signal immediately, but it might not have its “real” value until after the parent sets it. You can use computed() and effect() to react to input changes reactively, which often eliminates the need for ngOnInit entirely. An effect that reads input signals will automatically re-run when the parent changes the input — no lifecycle hook needed.
Strong Answer: A blank page with no errors is almost always a bootstrap or selector mismatch issue. My debugging sequence: First, I check index.html to confirm the app-root tag is present and matches the selector in AppComponent. If the selector is app-root but index.html has app-component, nothing renders and there is no error. Second, I check main.ts to ensure bootstrapApplication is called with the correct component and config. Third, I check app.config.ts to make sure provideRouter(routes) is included if I expect routing. Fourth, I open the browser’s Network tab to verify JavaScript files loaded successfully — a 404 on main.js would cause a blank screen. Fifth, I check the Angular tab in DevTools (if the extension is installed) to see if the component tree exists at all.If all of that looks fine, the issue might be that routes are defined but the root template is missing a router-outlet, or the default route redirects to a path that does not match any route definition (a missing pathMatch: ‘full’ on the redirect is a classic culprit).Follow-up: How would your approach differ if there WERE errors in the console? Answer: Then I read the error. The most common ones: “NullInjectorError: No provider for X” means a service is not providedIn root and was not added to providers. “NG0300: Multiple components match node with tagname X” means duplicate component selectors. “NG0100: Expression has changed after it was checked” means a value changes during change detection, usually from a getter or method call in the template that returns different values on consecutive reads.

Next Steps

Next: Components Deep Dive

Learn about component architecture, data binding, and communication patterns