Exploring Angular’s linkedSignal
: Enhancing Signal Reusability
In Angular applications, managing state and reactivity often involves tools like BehaviorSubject
from RxJS. With the advent of signals, particularly linkedSignal
, Angular provides a declarative and more Angular-native approach to handling dynamic state transformations.
Let’s build a product filtering example to see how linkedSignal
can simplify state management and potentially replace BehaviorSubject
.
In this post, we’ll explore what linkedSignal
is, its benefits, how it can replace BehaviorSubject
in many use cases, and how you can implement it in your Angular applications.
What is linkedSignal
?
The linkedSignal
function allows you to create a signal whose value is derived from other existing signals. Unlike computed signals that focus on recalculating values reactively, linkedSignal
is more tailored for situations where the new signal’s lifecycle and reactivity are closely tied to another signal or context.
This makes linkedSignal
a perfect choice when:
- You need to extend or transform the behavior of an existing signal.
- You want to maintain a scoped reactive context within your application.
Why Replace BehaviorSubject
with Signals?
Traditionally, Angular developers have relied on BehaviorSubject
from RxJS for state management, such as holding and propagating reactive data. While powerful, BehaviorSubject
has limitations that linkedSignal
can address:
1. Boilerplate Reduction
With BehaviorSubject
, you often have to write additional boilerplate for initialization, subscriptions, and updates:
const subject = new BehaviorSubject<number>(0);
subject.next(5);
subject.subscribe(value => console.log(value));
In contrast, linkedSignal
provides a more concise and declarative API:
const baseSignal = signal(0);
const linked = linkedSignal(() => baseSignal() * 2);
console.log(linked());
2. Declarative State Management
linkedSignal
eliminates the need for manual subscription management, reducing the risk of memory leaks and simplifying code structure. It’s purely declarative, meaning dependencies and updates are handled automatically.
3. Tight Integration with Angular
Unlike BehaviorSubject
, which is an external library feature, linkedSignal
is natively supported in Angular, ensuring seamless integration with other Angular features like templates and change detection.
Scenario: Product Filtering
Imagine you have a list of products, and the user can filter them by category. Using linkedSignal
, we can create a reactive filtered list that updates automatically whenever the category or product list changes.
import { Component, signal, linkedSignal } from '@angular/core';
@Component({
selector: 'app-product-filter',
standalone: true,
template: `
<h2>Product Filter</h2>
<div>
<label>Filter by Category:</label>
<select [value]="selectedCategory()" (change)="selectCategory($event.target.value)">
<option value="all">All</option>
<option *ngFor="let category of categories" [value]="category">
{{ category }}
</option>
</select>
</div>
<div>
<h3>Products</h3>
<ul>
<li *ngFor="let product of filteredProducts()">
{{ product.name }} - {{ product.category }}
</li>
</ul>
</div>
`,
})
export class ProductFilterComponent {
// Base signal for the list of products
products = signal([
{ name: 'Laptop', category: 'Electronics' },
{ name: 'Headphones', category: 'Electronics' },
{ name: 'Sofa', category: 'Furniture' },
{ name: 'Table', category: 'Furniture' },
{ name: 'T-shirt', category: 'Clothing' },
]);
// Signal for selected category
selectedCategory = signal<string>('all');
// Derived signal for filtering products based on the selected category
filteredProducts = linkedSignal(() => {
const category = this.selectedCategory();
const allProducts = this.products();
return category === 'all'
? allProducts
: allProducts.filter(product => product.category === category);
});
// Generate a list of unique categories from the products
get categories() {
return Array.from(new Set(this.products().map(product => product.category)));
}
// Update the selected category
selectCategory(category: string) {
this.selectedCategory.set(category);
}
}
Component Code
How It Works
- Signal Initialization:
products
contains a static list of products.selectedCategory
holds the currently selected category.
- Linked Signal:
filteredProducts
derives its value based onproducts
andselectedCategory
. It automatically recalculates when either signal changes.
- Reactivity in Action:
- When the user selects a category, the
filteredProducts
signal updates the displayed list of products dynamically.
- When the user selects a category, the
- If we used
BehaviorSubject
:- Set up a subject,
- add pipe for transformations,
- add manual subscriptions or async pipe.
- With
linkedSignal
:- Avoid subscriptions entirely.
- Use Angular’s built-in reactivity for value updates.
- Keep the code cleaner and more concise.
Benefits of This Approach
- Dynamic Updates: Any change in the product list or selected category immediately updates the filtered list.
- Code Clarity: The filtering logic is encapsulated within the
linkedSignal
, making it reusable and easier to test. - Performance: Signals ensure efficient updates with minimal recalculations.
When to Use linkedSignal
Instead of BehaviorSubject
Consider using linkedSignal
when:
- You are managing state within Angular components or services.
- You want a simpler, Angular-native alternative to RxJS subjects.
- The logic requires automatic dependency tracking and updates.
However, if you’re managing streams from external sources (e.g., WebSocket connections or complex asynchronous workflows), BehaviorSubject
or other RxJS operators may still be more appropriate.
Conclusion
Angular’s linkedSignal
simplifies state management by allowing you to derive signals dynamically. This product filter example demonstrates how you can build responsive and dynamic applications with ease.
Give it a try in your next Angular project, and let me know if you want more examples or use cases!
Code link:
git clone https://github.com/kategable/stackblitz-starters-linkedSignal.git
stackblitz – https://stackblitz.com/~/github.com/kategable/stackblitz-starters-linkedSignal?file=src/app/demo/demo.component.ts
get more Angularv19 here https://blog.angular.dev/meet-angular-v19-7b29dfd05b84