How to Create Angular Signals?
Tuesday, April 15, 2025Angular signals are a robust and easy-to-use feature that developers leverage to write reactive programs. Signals gained significant popularity upon its release with the launch of Angular 17 and are here to stay. This feature focuses on identifying errors, updating content, and determining which parts of your app need modifications. Data modification is no longer an overwhelming job. With the intuitive interface of signals, everything becomes more manageable.
Not just for reactive app development, but many reputable Angular development companies also utilize Signals to enhance runtime performance. When used correctly, Angular Signals can prove to be a game changer.
To understand Angular signals, it’s important to understand their working, functionality, creation, and usage. Fortunately, all these aspects are covered in the article below.
1. What Do You Mean by Angular Signals?
Angular Signals are specially designed observables that notify the entire application and other code about changes in asynchronous data, regardless of how minor those changes may be.
Serving as reactive primitives, Angular signals establish a publisher-subscriber relationship with the observers. In this setup, the publisher represents a value communicated to the subscriber. In case of a change, new values are also relayed easily.
With signals, data synchronization within your Angular app improves, along with its overall responsiveness. Many Angular components, services, and templates leverage signals for data exchange. This allows developers to optimize the performance of the application. In the end, it helps elevate the user experience with each release.
2. Why Do We Need Signals?
Let’s consider an example to understand the need to use Angular signals. Assume you are writing a code that does simple multiplication.
let a = 3;
let b = 4;
let c = a * b;
console.log(c);
The execution of this code will display 12 in the console as c is the result of multiplying a and b.
If we change the value of a, will the value of c also change? Well, the simple math suggests that the resulting value c would also change. But the console will continue to log 12. Why is that?
When the expression was evaluated the first time, the variable c was assigned the value 12. And c is not the kind of variable that updates automatically to the changes in a or b.
With Angular signals, applications can react to the changes effectively. Developers often prefer Angular to design reactive websites because it allows utilizing Angular signals, which enhances the reactivity of your code. See how it changes your code:
const a = signal(3);
const b = signal(4);
const c = computed(() => a() * b());
console.log(c()); // 12
a.set(6);
console.log(c()); // 24
With this reactive code, your code accurately reflects changes in inputs, even if they change frequently. In addition, signals provide fine control over change detection, which can significantly help improve the application performance.
3. Creating Angular Signals
Signals are reactive values that are continuously observed. And upon any changes, it sends a notification to all the dependents.
Next, create an Angular service to manage signals.
import { Injectable, signal } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class ProfileService {
// Signal to store profile name
profileName = signal('John Doe');
updateName(newName: string) {
this.profileName.set(newName);
}
}
Inject this service in your Angular components to subscribe to and update profile name using signals.
import { Component } from '@angular/core';
import { ProfileService } from '../services/profile.service';
@Component({
selector: 'app-profile',
template: `
Profile Name: {{ profileService.profileName() }}
`,
styleUrls: ['./profile.component.css'],
})
export class ProfileComponent {
newName = '';
constructor(public profileService: ProfileService) {}
updateProfile() {
if (this.newName.trim()) {
this.profileService.updateName(this.newName);
this.newName = '';
}
}
}
At the click of a button, all the subscribing components will receive the emitted data from the Angular signal.
4. Reading the Signal’s Value
Every signal represents a value, but these values are wrapped inside a signal itself. To access these values, you just need to call the signal as a function without passing the arguments.
It would feel like you ordered something and received a box. You have to open the box to see what’s inside. Here, you open the signal to read its value by adding parentheses such as quantity();.
Let us understand this with an example. Here, you will be writing a function that retrieves the signal, starting with the name of the signal, followed by parentheses. This signal-getter function won’t appear directly in your code. But in Angular, it is commonly used in a template.
Food: {{ selectedFood().name }}
Price: {{ selectedFood().price }}
Total: {{ totalAmount() }}
quantity = signal(1);
availableQuantity = signal([1, 2, 3, 4, 5, 6]);
selectedFood = signal({
id: 1,
name: 'Burger',
price: 19.13
});
onQuantitySelect(qty: number) {
this.quantity.set(qty);
}
totalAmount = computed(() => this.selectedFood().price * this.quantity());
color = computed(() => this.totalAmount() > 50000 ? 'green' : 'blue');
This template shows the select box to select a quantity, with the [ngModel] bound to the current value of the quantity signal.
The onQuantitySelect() method is triggered in the component through the change event binding. Using ngFor, the option elements iterate over each element in the availableQuantity signal. After reading the signal, it moves forward to creating a select option for every array element.
The template consists of three div elements. The first div accesses the name property of the selectedFood signal whereas the second displays its price property. The third div element reads the totalAmount signal which is yet undefined to set the text color (undefined) for value from the color signal.
Remember, the code can only read the current value of the signal. It doesn’t retain information about its prior values.
5. Changing the Value of Angular Signal
In Angular, signals may not remain the same; their values can change over time. Here are three different ways to change the value of an Angular signal.
- set() Method – Use this method to replace the currently presented value of your Angular signal with a new one. When you add a new variable, the old one is discarded.
- update() Method – Use the update() method when you need to update the value of an existing Angular signal. In this scenario, your function will take the existing value as an argument and add the new value without replacing the old one.
- mutate() Method – Now, this method is a combination of the both given above. You can modify an existing value without replacing it entirely. The mutate() method helps you direct mutations with the current signal value. Here you don’t need to create a new object, you can just simply modify the properties of the existing one.
6. The computed() Signal
In some instances, signals can be created or derived from other signals. In that case, updating a signal will automatically update all its dependent signals. An example would help you understand it better.
Let’s assume you need a countDoubler on a component, and it will double the value of the actual count. Now, derive a signal from the counter signal using computed() API:
@Component(
selector: "app",
template: `
Counter value {{counter()}}
Double of counter: {{countDoubler()}}
`)
export class AppComponent {
counter = signal(0);
countDoubler = computed(() => {
return this.counter() * 2;
})
increment() {
console.log(`Updating counter...`)
this.counter.set(this.counter() + 1);
}
}
The computed API creates a new signal by using one or more source signals. Any changes in the source signal are immediately reflected in the computed signal, known as cDoubler.
Explanation of the Code:
- Item Price: A signal representing the price of a single item.
- Quantity: A variable bound to an input field, allowing users to specify how many items they want to purchase.
- Tax Rate: A constant representing the tax percentage.
- Total Price: A computed signal that calculates the total price based on the item price, quantity, and tax rate. It updates automatically when any of its dependencies change.
- Add to Cart: A method that simulates adding items to the cart.
When you change the quantity in the input field, the total price will update automatically to reflect the new total, including tax.
7. The effect() Signal
Signal emission can lead to unintended side effects, especially when the value changes. Along with the dependent components, the code may sometimes also call APIs or perform unrelated operations. To manage this side effect, you can use the effect() function.
Take an example where you want to debug your signals and log out a value every time the code reacts to the changes. In this case, calling the console.log() is a common side effect.
To handle this, first call the effect() function and pass in the operation you want to perform. It will define the effect and will be reperformed every time your code reacts to the changes in any one of the dependent signals.
effect(() => console.log(this.selectedFood()));
Calling the effect() function is carried out within another function. Sometimes, you also need another startup code or constructor to handle the effects.
There is another way to define the effect; do it declaratively.
The effect signal is not effective for updating the value of the signals when dependent signals change. For that, you have to employ a computed signal. Since you won’t be using the effect frequently, it’s better suited for purposes like logging and calling external APIs.
8. Conclusion
This article is a comprehensive guide to Angular signals, covering everything from the introduction to explaining how to create and use it. You also learned how you can create computed values and effects with signals.
Remember that it’s Angular signals that help make your code more reactive. It is a robust and expressive way to handle state changes and data flow in your Angular application. Through them, creating responsive and interactive UIs becomes straightforward.
FAQs
What are Angular signals?
Angular Signals are a robust feature that helps developers build reactive applications.
Are Signals better than Observables?
Of course, signals are better than observables in an Angular template. They don’t need pipes for scheduling change detection. You can use it to read the same signal over and over again. And unlike other features, signals never glitch.
Comments