Signals are a new method to track state within Angular. They were introduced in preview in Angular 16 and officially released in Angular 17.

A signal can be writeable or read-only.

With signals, data flows from the source signal down to it’s children. Each notifying if its value has actually changed. This inverts the flow of data within Angular applications

Replacing component variables with signals

In most codebases, public variables are used to display data or perform checks within component templates.

Currently:

public name: string | undefined; public isExpanded = false;

These can be comfortably changed to writeable signals:

public readonly name = signal<string | undefined>(); public readonly isExpanded = signal<boolean>(false);

You can pass default values to a signal by passing a value as the signal function argument.

These signals can then be modified with either the set function or the update function.

this.name.set("Starfisk"); this.isExpanded.update((current) => !current);
Usingset replaces the current value with a new one. While update allows running a function starting from the current value of the signal.

Replacing Getters with Computed Signals

Often in component templates, you may want to display the result of some calculation using existing variables. for example calculating a person’s age or concatenating their full name.

This is where computed signals come in. They can take the values from other signals and provide a derived value.

Previously:

public person = { firstName: "John", lastName: "Doe", }; public get displayName(): string { return ${this.person.firstName} ${this.person.lastName.substring(0, 1)}.; } public get greeting(): string { return Hello ${this.displayName}|; }

This can be written with signals like this:

public readonly person = signal({ firstName: "John", lastName: "Doe", }); public readonly displayName = computed(() => ${this.person().firstName} ${this.person().lastName.substring(0, 1)}.); public readonly greeting = computed(() => Hello ${this.displayName()}!);

This is the inversion of flow of data we spoke of earlier. Normally Angular constantly has to check and run the code in displayName and greeting for changes when displaying it in the template. Meanwhile with signals, the person signal notifies the displayName signal whenever it changes, which in return notifies greeting if it too has changed.

Component input

Components often receive their data through the Input decorator on variables. This allows a parent component to share its data, one way, to a child component using the Input decorator.

Signals provide a new input function to define this relationship.

Previously, to receive data from the parent we would write this code:

@Input({ required: true }) public firstName: string; @Input() public lastName: string;

We can simplify this code as follows:

public readonly firstName = input.required<string>(); public readonly lastname = input<string>();

With this syntax we gain all the advantages of our writeable signals, including using them inside computed signals.

Conclusion

Now you can take advantage of Angular signals within your existing application! Replacing your existing component code to leverage signals.