Skip to content
View lessons Login
3d cartoon hands holding a phone

Unlock full course by purchasing a membership

An Introduction to Signals

An Introduction to Signals

Signals are one of the new features in Angular, and it is pretty safe to say they are the new feature.

It might be hard to see why… or even understand what exactly it is they allow us to do.

For example, here is a basic interpolation that we have already covered:

import { Component } from '@angular/core';
@Component({
selector: 'app-home',
template: `<p>Hi, {{ name }}</p>`,
})
export class HomeComponent {
name = 'Josh';
}

Now here is what it will look like with signals:

import { Component, signal } from '@angular/core';
@Component({
selector: 'app-home',
template: `<p>Hi, {{ name() }}</p>`,
})
export class HomeComponent {
name = signal('Josh');
}

It’s basically exactly the same… except we have to wrap our Josh value with this signal function that is imported from @angular/core, and in the template we also have to use this funny syntax to access the value:

{{ name() }}

When we create our name:

name = signal('Josh');

It will become whatever this signal function we are calling returns. The signal function will actually return us something called a WritableSignal which is a type of signal (specifically, one you are allowed to update).

So, basically, the signal function will return us a signal. That means name is a signal.

To access the value of a signal we call it as a function — that is what we are doing in the template:

{{ name() }}

If we did this instead:

{{ name }}

You would see some nonsense like this in the template:

Hi, function signalFn() { producerAccessed(node); return node.value; }

So it seems that signals do basically the same thing as declaring a class member and using an interpolation, except that it requires extra syntax and comes with some extra confusing nonsense.

Signals and Change Detection

Ok, so given how excited everyone is about these things, it’s safe to say there is some benefit to them.

Perhaps the key thing is how they tie into change detection. This is a topic we are going to cover in a lot more depth in a few lessons time, but what is important to understand for now is that Angular needs to know when something has changed in order to update the view and actually display the change to the user.

For example:

import { Component } from '@angular/core';
@Component({
selector: 'app-home',
template: `<p>Hi, {{ name }}</p>`,
})
export class HomeComponent {
name = 'Josh';
}

If name changes from Josh to Kathy for any reason, Angular needs to know so that it can update the DOM appropriately. How does Angular keep track of when things change? To put it simply, it use a mechanism (Zone.js) that will notify it when anything possibly could have happened to cause a change. Things that could potentially cause a change are things like setTimeout or setInterval or a promise resolving, or an HTTP request completing, and so on.

Angular gets notified that there could have been a change, and then it checks every component to see if anything needs to be updated.

This isn’t as bad as it sounds — Angular can actually do this quite fast and there are ways to optimise it on the developers end. But, there is certainly room for improvement.

That is where signals come in. It flips this whole problem on its head. Instead of Angular checking whenever anything could have possibly changed, it becomes the role of the signal to tell Angular when it has changed.

If we use signals for our values that change, then it allows Angular to do a lot less change detection work. So, if we do something like this:

name = signal('Josh');
updateName(name: string) {
this.name.set(name);
}

We are calling set on our signal which will update its value, but it can also notify Angular that it has changed. It’s also not just Angular that it will notify about the change, we can make use of this mechanism as well (more on that later).

It’s important to note that these change detection changes have not actually been implemented in Angular yet, they will be coming soon in an update. However, as we go through this course we will basically just be pretending that these changes are already in place. Using signals with the current/default change detection strategy will still work anyway, and when the change detection updates do land we will just get all of the benefits for free without needing to change anything.

Basic Signals API

We will be talking about signals a lot in this course. For now, let’s just get a basic understanding of the API.

As we have seen, we can create a signal:

name = signal('Josh');

and access its value as a function:

name()

We can also update a signal’s value with set:

this.name.set(name);

We can also update a signal’s value with the update method. The benefit of this approach is that it gives us a reference to the existing value. This becomes useful when dealing with objects in a signal. For example:

preferences = signal({
fast: true,
comfortable: true,
expensive: false,
});
toggleComfort() {
this.preferences.update((preferences) => ({
...preferences,
comfortable: !preferences.comfortable,
}));
}

Our signal now contains an object. In the toggleComfort method we want flip the boolean for the comfortable property. By using the update method we spread the existing preferences into a new object so that we can keep all of its existing values, and then we supply a new value for the comfortable property which will be the opposite of whatever it currently is.

STANDARD STANDARD

Thanks for checking out the preview of this lesson!

You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).