Angular 17 Signals Explained

Angular 17 Signals Explained

Angular 17 includes a new feature called Signals that allows you to define reactive values and describe dependencies between them. Signals can be editable or read-only.

Signals are an interesting new feature coming to Angular! Signals give our code a new mechanism to notify our templates (and other code) that our data has undergone modifications. This increases the detection of changes in Angular, which improves efficiency and makes our code more reactive.

Angular Signals add three reactive primitives to Angular 16+, allowing you to create reactive apps without the use of RxJS.

According to the Angular documentation, a signal is:

A value wrapper that can inform interested subscribers when the value changes. Signal values can range from simple primitives to complicated data structures.

The value of a signal is always read via a getter function, which allows Angular to trace where the signal is utilized.

A signal may be thought of as a value plus an alteration notice. A signal is just a sort of variable that stores a value. A signal, however, unlike other variables, also gives notification when the variable value updates.

Where are signals useful?

  • Use them in components to track the current state of local components.
  • Use them in directives.
  • Utilize them in a service to exchange state across components.
  • To show signal values, read them into a template.
  • Or utilize them anywhere in your code.

How to define a signal

You can define a signal using the following syntax:

price = signal<number>(10);

Using the signal constructor function, the aforementioned syntax establishes and initializes a signal.

Provide a generic type argument to describe the data type of the signal if desired. A signal can be a text, a number, an array, an object, or any other sort of data. In many circumstances, the data type may be deduced, making the generic type parameter obsolete.

Pass the signal's default value to the constructor. A signal always has a value, which begins with the default.

How to read a signal value

You can read the signal value using the following syntax:

price(); 

Begin with the signal name, followed by open and closed parentheses. This is referred to as the signal's getter function. The getter function is constructed in the background and is not visible in your code.

A popular area to read signals while working with Angular is in the template.

How to change a Signal's value

The signal set method changes a signal's value with a new one. It simply opens the box (Signal), removes the existing item, and replaces it with a fresh item.

This is the syntax:

this.price.set(20);

The code alerts any consumers that the signal has changed whenever it is set. A consumer in this sense is any part of code that is interested in getting change notifications.

How can a consumer indicate that he or she wants to receive notifications concerning a certain signal?

When code reads a signal, it is alerted whenever the signal changes.

A template that reads a signal is informed when the signal changes and the view is scheduled to be re-rendered.

Aside from set(), there are two more methods for changing a signal: update() and mutate().

The set() method replaces a signal with a new value, symbolically replacing the signal box's contents. You can invoke the set method with the updated value as follows:

this.price.set(30);

The signal is updated using the update() function depending on its current value. Pass an arrow function to the update method. The arrow function delivers the current signal value, which can be updated as needed. The amount is doubled in the code below:

// Update value based on current value
this.price.update(p => p * 2);

The mutate() method changes the content of a signal value rather than the value itself. It may be used with arrays to change array items and objects to change object attributes.

Consumers are told that the signal has been altered, regardless of how it is updated. When it is time to execute, the consumers can read the new signal value.

Angular 17 Signals example

Assume you have an e-commerce application that allows customers to add products to their shopping basket. You want to show the total price of the goods and have it updated whenever a new item is added or removed. Here's how you can do that with Signals:

@Component({  
  selector: 'my-cart',  
  template: `  
    <ul>  
      <li *ngFor="let item of goods">  
         - $  
        <button (click)="removeItem(item)">Remove</button>  
      </li>  
    </ul>  
    Total Price: $  
  `,  
})  
export class CartComponent {  
  goods = [    { name: 'Product 1', price: 10 },    { name: 'Product 2', price: 20 },    { name: 'Product 3', price: 30 },  ];  

  // Define a signal for the list of items  
  itemList = signal(this.goods);  

  // Define a computed value for the total price  
  total = computed(() => {  
    return this.itemList().reduce((acc, curr) => acc + curr.price, 0);  
  });  

  removeItem(item) {  
    // Update the itemList signal by removing the selected item  
    this.itemList.set(this.itemList().filter((i) => i !== item));  
  }  
}

In this example, we establish a signal itemList for the cart's list of items and a computed value total price that is dependent on itemList. When an item is removed from the the basket, we update the itemList signal, which causes the total price to be recalculated.