Angular Tutorial 0/42 lessons ~6 min read Lesson 23

    Angular Signals

    Learn Angular Signals, including signal(), set(), update(), computed(), effect(), dependency tracking, OnPush, control flow, HttpClient, RxJS interoperability (toSignal/toObservable), Signal Stores, enterprise architecture, performance, common mistakes, and interview questions.

    Course progress0%
    Focus
    31 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Learning Objectives

    By the end of this lesson, you will understand:

    • What Angular Signals are and why they were introduced.
    • How Signals improve state management.
    • The difference between Signals and traditional Angular change detection.
    • How to create writable Signals using signal().
    • How to read Signal values.
    • How to update Signals using set() and update().
    • How computed() creates derived state.
    • How effect() reacts to Signal changes.
    • Writable vs read-only Signals.
    • Signal dependency tracking.
    • Dynamic dependency tracking.
    • Signal equality.
    • Signals with Components.
    • Signals with OnPush Change Detection.
    • Signals with @if, @for, and @switch.
    • Signals with HttpClient.
    • Signals with RxJS (toSignal() and toObservable()).
    • Building scalable Signal Stores.
    • Enterprise state management architecture.
    • Performance optimization.
    • Real-world examples.
    • Common mistakes.
    • Advanced interview questions.

    Introduction

    Every Angular application has state.

    For example:

    text
    Current User
    Theme
    Courses
    Shopping Cart
    Notifications
    Loading Status
    Error Messages
    Authentication

    Whenever state changes, the UI should automatically update.

    Imagine TechLearningPro.

    text
    User Opens Angular Course
    Course Loads
    Lessons Display
    User Completes Lesson
    Progress Updates
    Certificate Unlocks

    Every one of these steps is a state change.

    Managing state efficiently is one of the biggest challenges in frontend development.

    What Are Angular Signals?

    Angular Signals are reactive state containers.

    A Signal stores a value and automatically notifies Angular whenever that value changes.

    Think of a Signal as a smart variable.

    Unlike a normal variable:

    typescript
    let count = 0;

    A Signal is reactive.

    typescript
    const count = signal(0);

    Architecture:

    text
    Signal
    State Changes
    Angular Detects Change
    Update UI

    Why Angular Introduced Signals

    Traditional Angular relied heavily on:

    • Zone.js
    • Global Change Detection
    • RxJS for local state

    This worked well but sometimes caused unnecessary checks.

    Signals introduce fine-grained reactivity.

    Instead of checking the whole application, Angular updates only the parts that depend on the changed Signal.

    Architecture:

    text
    Before
    Application
    Change Detection
    Many Components Checked
    -----------------------------------
    With Signals
    Signal Changed
    Only Dependent Components Update

    Creating Your First Signal

    Use the signal() function.

    typescript
    import { signal } from '@angular/core';
    count = signal(0);

    The Signal now stores the value 0.

    Reading a Signal

    Signals are read by calling them like a function.

    typescript
    count();

    Example:

    typescript
    console.log(count());

    Output:

    text
    0

    Architecture:

    text
    Signal
    count()
    Value

    Updating a Signal using set()

    Use set() when replacing the value completely.

    typescript
    count.set(10);

    Now:

    typescript
    count();

    returns:

    text
    10

    Updating a Signal using update()

    Suppose the current value is:

    text
    10

    Increment:

    typescript
    count.update(value => value + 1);

    Result:

    text
    11

    Architecture:

    text
    Current Value
    update()
    New Value

    set() vs update()

    Use:

    typescript
    count.set(100);

    when replacing the value.

    Use:

    typescript
    count.update(v => v + 1);

    when calculating a new value from the current value.

    Real-Time Counter Example

    typescript
    count = signal(0);
    increment() {
    this.count.update(v => v + 1);
    }

    Template:

    html
    <p>{{ count() }}</p>
    <button (click)="increment()">
    Increment
    </button>

    Architecture:

    text
    Button Click
    update()
    Signal Changes
    UI Updates

    Signals with Objects

    Signals can store objects.

    typescript
    user = signal({
    id: 1,
    name: 'Jagannath',
    role: 'ADMIN'
    });

    Read:

    typescript
    user().name

    Update:

    typescript
    user.update(u => ({
    ...u,
    role: 'STUDENT'
    }));

    Signals with Arrays

    Example:

    typescript
    courses = signal([
    'Angular',
    'Java',
    'Spring Boot'
    ]);

    Add a course:

    typescript
    courses.update(list => [
    ...list,
    'Kubernetes'
    ]);

    Architecture:

    text
    Courses Signal
    Update Array
    Angular UI Updates

    computed()

    Many values are derived from other values.

    Suppose:

    typescript
    price = signal(1000);
    quantity = signal(3);

    Total price should always be:

    text
    3000

    Instead of manually calculating it everywhere:

    Use:

    typescript
    total = computed(() =>
    this.price() * this.quantity()
    );

    Architecture:

    text
    Price Signal
    Computed
    Quantity Signal
    Total

    Whenever either Signal changes, the computed Signal updates automatically.

    Real-Time Example: TechLearningPro Progress

    Signals:

    typescript
    completedLessons = signal(18);
    totalLessons = signal(25);

    Computed:

    typescript
    progress = computed(() =>
    (this.completedLessons() / this.totalLessons()) * 100
    );

    Output:

    text
    72%

    No manual calculation is required.

    effect()

    Sometimes we don't want to calculate a value.

    We want to perform an action.

    For example:

    text
    Save Progress
    Analytics
    Logging
    Notifications

    Use:

    typescript
    effect(() => {
    console.log(this.count());
    });

    Whenever count changes:

    text
    Console Updates Automatically

    Architecture:

    text
    Signal Changes
    effect()
    Side Effect

    Writable vs Read-only Signals

    Writable:

    typescript
    count = signal(0);

    Read-only:

    typescript
    progress = computed(...);

    Architecture:

    text
    signal()
    Writable
    computed()
    Read Only

    Dependency Tracking

    Angular automatically tracks dependencies.

    Example:

    typescript
    total = computed(() =>
    this.price() * this.quantity()
    );

    Angular knows:

    text
    Total
    Depends On
    Price
    Quantity

    If either changes:

    Only total recomputes.

    Dynamic Dependency Tracking

    Signals only track values actually read during execution.

    Example:

    typescript
    showPrice = signal(true);
    price = signal(100);
    discount = signal(20);
    display = computed(() => {
    if (this.showPrice()) {
    return this.price();
    }
    return this.discount();
    });

    When showPrice() is true:

    Only price() is tracked.

    Signals with Components

    Example:

    typescript
    @Component({...})
    export class DashboardComponent {
    user = signal('Jagannath');
    }

    Template:

    html
    <h2>
    {{ user() }}
    </h2>

    Whenever:

    typescript
    user.set('Krishna');

    Angular automatically updates the UI.

    Signals with OnPush Change Detection

    Traditionally, OnPush components required careful management of immutable data and change detection.

    Signals work naturally with OnPush.

    Architecture:

    text
    Signal Changes
    OnPush Component
    Only Required View Updates

    This helps create highly performant applications.

    Signals with Control Flow

    Signals integrate perfectly with modern control flow.

    Example:

    html
    @if (isLoggedIn()) {
    <app-dashboard />
    } @else {
    <app-login />
    }

    Collection:

    html
    @for (
    course of courses();
    track course.id
    ) {
    <app-course-card />
    }

    Signals with HttpClient

    Example:

    typescript
    courses = signal<Course[]>([]);
    loading = signal(true);
    this.http.get<Course[]>(...)
    .subscribe(data => {
    this.courses.set(data);
    this.loading.set(false);
    });

    Template:

    html
    @if (loading()) {
    <app-spinner />
    } @else {
    @for (
    course of courses();
    track course.id
    ) {
    <app-course-card />
    }
    }

    Signals and RxJS

    Angular provides interoperability.

    Observable → Signal

    typescript
    toSignal()

    Signal → Observable

    typescript
    toObservable()

    Architecture:

    text
    Observable
    toSignal()
    Signal
    toObservable()
    Observable

    This allows gradual migration from RxJS.

    Building a Signal Store

    Instead of placing Signals inside many components:

    Create a feature store.

    Example:

    typescript
    @Injectable()
    export class CourseStore {
    courses = signal<Course[]>([]);
    loading = signal(false);
    error = signal('');
    }

    Architecture:

    text
    Component
    Course Store
    Signals
    API

    TechLearningPro Signal Architecture

    text
    Course Store
    ├── courses()
    ├── loading()
    ├── progress()
    ├── selectedLesson()
    ├── completedLessons()
    └── searchText()
    Computed Signals
    Filtered Lessons
    Angular UI

    This architecture scales very well.

    Performance Benefits

    Signals provide:

    text
    Fine-Grained Updates
    Less Change Detection
    Cleaner State
    Better Performance
    Simpler Components

    Common Mistakes

    Mutating Objects

    Avoid:

    typescript
    user().name = 'Krishna';

    Instead:

    typescript
    user.update(u => ({
    ...u,
    name: 'Krishna'
    }));

    Using effect() Everywhere

    Effects are for side effects.

    Don't use them for derived values.

    Use:

    text
    computed()

    instead.

    Business Logic Inside Components

    Move Signals into feature stores.

    Too Many Global Signals

    Keep Signals close to the feature that owns them.

    Enterprise Architecture

    text
    Backend API
    Course Service
    Course Store
    Signals
    Computed Signals
    Angular Components
    UI

    This is the recommended architecture for scalable Angular applications.

    Advanced interview questions

    Interview Prep

    Practice concise answers, then expand each card for the explanation.

    10 questions
    1BeginnerQuestionWhat is an Angular Signal?+

    Answer

    A Signal is a reactive state container that automatically notifies Angular when its value changes, allowing Angular to update only the affected parts of the UI.
    2BeginnerQuestionHow do you create a Signal?+

    Answer

    count = signal(0);
    3BeginnerQuestionHow do you read a Signal?+

    Answer

    count();
    4BeginnerQuestionDifference between `set()` and `update()`?+

    Answer

    • set() replaces the value completely.
    • update() calculates a new value based on the current value.
    5IntermediateQuestionWhat is `computed()`?+

    Answer

    A read-only Signal whose value is automatically derived from one or more other Signals.
    6IntermediateQuestionWhat is `effect()`?+

    Answer

    effect() executes side effects whenever the Signals it reads change. It is commonly used for logging, analytics, local storage synchronization, or other side-effect operations.
    7AdvancedQuestionCan Signals replace RxJS?+

    Answer

    Not completely. Signals are excellent for local and component-level state. RxJS remains valuable for asynchronous event streams, complex operators, and many HTTP or WebSocket scenarios. They complement each other.
    8IntermediateQuestionWhy are Signals faster?+

    Answer

    Signals enable fine-grained reactivity, so Angular updates only the views that depend on changed Signals instead of broadly checking unrelated parts of the application.
    9IntermediateQuestionCan Signals work with OnPush?+

    Answer

    Yes. Signals integrate naturally with OnPush components and help simplify efficient UI updates.
    10AdvancedQuestionWhat is the recommended enterprise architecture?+

    Answer

    Backend → Service → Signal Store → Computed Signals → Components → UI. This separates business logic, state management, and presentation, making applications easier to maintain and scale.

    Summary

    Angular Signals simplify reactive state management while improving performance and readability.

    text
    Backend API
    Service Layer
    Signal Store
    ├── Writable Signals
    ├── Computed Signals
    └── Effects
    Angular Components
    @if / @for / @switch
    User Interface

    The most important principle is:

    The most important principle is: Use Signals to represent state, computed() to derive state, and effect() only for side effects. Keep business logic in services or stores and let components focus on rendering.

    Next Lesson

    Angular Change Detection — In the next lesson, you'll learn:

    • How Angular Change Detection works internally.
    • Default vs OnPush Change Detection.
    • Zone.js and its role.
    • Zoneless Angular.
    • Change detection tree and traversal.
    • ChangeDetectorRef.
    • markForCheck() vs detectChanges().
    • detach() and reattach().
    • Signals and Change Detection.
    • Performance optimization techniques.
    • Debugging change detection issues.
    • Enterprise best practices.
    • Advanced interview questions.
    Ready to mark this lesson complete?Track your journey across the entire course.