Skip to content
beginner Phase 11 · Signals and Change Detection

Creating and Updating Signals

Hold reactive values with signal, set, and update.

40m
0 problems
Topic Progress 0%

Creating Signals

Signals are reactive containers for values. When a signal changes, all dependent computations and templates automatically update.

Creating a Signal

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

@Component({
  selector: 'app-counter',
  template: `
    <p>Count: {{ count() }}</p>
    <button (click)="increment()">+</button>
    <button (click)="decrement()">-</button>
  `,
})
export class CounterComponent {
  count = signal(0);

  increment(): void {
    this.count.update(c => c + 1);
  }

  decrement(): void {
    this.count.update(c => c - 1);
  }
}

set() vs update()

// set() — replace the value directly
this.count.set(10);

// update() — compute new value from current
this.count.update(c => c + 1);

Reading Signals

// In component class — call as function
const currentValue = this.count();

// In template — call as function
<p>{{ count() }}</p>

Signal Types

// Primitive
const name = signal<string>('Alice');

// Object
const user = signal<User>({ id: 1, name: 'Alice' });

// Array
const items = signal<string[]>([]);

// Readonly (prevent external writes)
const readonlyCount = this.count.asReadonly();

Computed Signals

Computed signals derive values from other signals. They are lazy and memoized.

Creating Computed Signals

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

@Component({
  selector: 'app-cart',
  template: `
    <p>Items: {{ itemCount() }}</p>
    <p>Total: {{ total() | currency: 'USD' }}</p>
    <p>Tax: {{ tax() | currency: 'USD' }}</p>
    <p>Grand Total: {{ grandTotal() | currency: 'USD' }}</p>
  `,
})
export class CartComponent {
  items = signal<CartItem[]>([
    { name: 'Widget', price: 10 },
    { name: 'Gadget', price: 20 },
  ]);

  itemCount = computed(() => this.items().length);

  total = computed(() =>
    this.items().reduce((sum, item) => sum + item.price, 0)
  );

  tax = computed(() => this.total() * 0.1);

  grandTotal = computed(() => this.total() + this.tax());
}

Computed Signal Characteristics

  1. Lazy — Only computed when read
  2. Memoized — Cached until dependencies change
  3. Read-only — Cannot be set or updated
// BAD: Computed signals are read-only
this.total.set(100); // Error!

// GOOD: Update the source signal
this.items.update(items => [...items, newItem]);

Computed with Conditions

const isEligible = computed(() =>
  this.age() >= 18 && this.hasConsent()
);

const message = computed(() => {
  if (this.isEligible()) {
    return 'Access granted';
  }
  return 'Access denied';
});

Quiz

1. How do you create a signal?

Question 1 options

2. What is a computed signal?

Question 2 options

3. How do you update a signal based on its current value?

Question 3 options

Flashcards

Question

How do you create a signal?

Answer

signal(value) — read with signal(), update with set() or update().

Question

What is a computed signal?

Answer

Derived signal that is lazy and memoized. Read-only.

Question

set() vs update()?

Answer

set() replaces the value. update() computes new value from current.

Revision Notes

Key Takeaways

  • 1. signal() creates reactive values
  • 2. Read signals by calling them: signal()
  • 3. set() replaces, update() derives from current
  • 4. computed() creates lazy, memoized derived values

Interview Tips

  • • Explain the difference between set() and update()
  • • Be ready to describe computed signal characteristics
  • • Mention that signals enable fine-grained reactivity

Cheat Sheet

Signals Cheat Sheet

Create:

count = signal(0);

Read:

count() // in class or template

Update:

count.set(10);
count.update(c => c + 1);

Computed:

total = computed(() => this.items().reduce((s, i) => s + i.price, 0));

Readonly:

readonlySignal = signal.asReadonly();

Continue Learning