Angular Signals: Part 1 — Introduction

Bhargav R G
3 min readMay 27, 2024

--

In this article, I will explain the concept of Signals in Angular.

Signals are ready for production starting from Angular v18. I will be publishing a series on advanced concepts in signals. In this article, I am explaining the basic concepts of Signals.

I will cover:

  1. How to define a Signal.
  2. How to display a Signal’s value in a template.
  3. How to update a Signal’s value with set().
  4. How to update a Signal’s value with update().
  5. Compute Signal.
  6. Effect.

1. Define Signal:

Defining variable as signal

we are defining 2 signal variables

  1. counter is of type number.
  2. customer is of type CustomerI.

2. Display Signal’s value in a Template:

Displaying signal value in template.

we need to use parentheses to display value in signal.

3. Update signals value using set()

Updating signal value with set().

We need to use set() method if we want to assign new value to signal.

4. Update signals value using update()

Updating Signal with update().

Within the update() method, we need to pass an anonymous function. This function takes the current value as a parameter, allowing us to implement the logic to update the value.

  • this.counter.set(this.counter() + 1); is not recommended because it directly sets the value without considering the current state management best practices.
  • this.counter.update((previousValue) => previousValue + 1); is the correct approach. Here, update() accepts an anonymous function that takes the previous value (previousValue) as a parameter and returns the new value after applying the increment logic. This method ensures that the state is updated correctly and is more maintainable.

5. Computed Value:

Computed value.

In this example:

  • doubleCounter is a new signal derived from the counter signal.
  • The computed() function takes a function as its argument. This function calculates the new value for doubleCounter based on the current value of counter.
  • Whenever counter is updated, the computed function re-executes, ensuring that doubleCounter always reflects the current state of counter multiplied by 2.

6. Effect:

Effect

In this example:

  • Inside the constructor, we define an effect using the effect() function.
  • The effect() function takes an anonymous function as an argument, which calls this.counter().
  • This effect will execute whenever the counter signal is updated.
  • Within the effect, you can perform any side effects needed, such as logging, updating the UI, or triggering other actions.
Template
import { Component, computed, effect, signal } from '@angular/core';

@Component({
selector: 'app-cart',
standalone: true,
template: `
<p>Counter:- {{counter()}}</p>
<p>Double Counter:- {{doubleCounter()}}</p>
<p>Customer Name:-{{customer().name || 'N/A'}}</p>
<p>Customer ID:-{{customer().id || 'N/A'}}</p>
<button (click)="updateCustomer()">Update Customer</button>
<button (click)="increment()">Increment</button>
`,
})
export class CartComponent {

counter = signal<number>(0);
customer = signal<CustomerI>({ name: '', id: null });
doubleCounter = computed(() => this.counter() * 2);

constructor() {
effect(() => {
this.counter();
// we can perform side effects here.
})
}

updateCustomer() {
this.customer.set({ name: 'Signal', id: 18 });
}

increment() {
// this.counter.set(this.counter() + 1); // Dont do this.❌
this.counter.update((previousValue) => previousValue + 1); //✅
}

}

Reference: https://angular.dev/guide/signals

--

--

Bhargav R G

UI-Developer - Angular | React | Vue | NgRx | Redux | RxJS | Stencil.js | Web Components | Cypress | SCSS | NodeJS | NestJS | MongoDB | Elastic Search