DEV Community

Cover image for Angular Tips: Transforming Observables into Signals for Enhanced Reactivity
deji adesoga for This is Angular

Posted on • Originally published at newline.co

Angular Tips: Transforming Observables into Signals for Enhanced Reactivity

Unlock Your Angular Signals Knowledge with my New Course: Demystifying Reactivity with Angular Signals

Introduction

There’s always been a love-hate relationship with front-end devs and Angular.

It’s a really powerful framework, and yet so hard to get into it,

especially if you’re a newer engineer.

Thankfully, Angular keeps evolving, year by year, and continuously offerring better, easier, and more efficient ways to manage data and reactivity.

One such evolution is the conversion of observables to signals using Angular's interoperability API.

This post explores this transformative process and its significance in enhancing application reactivity and performance.

Understanding Observables and Signals in Angular

In Angular, observables are a core part of managing data streams, particularly when fetching data from REST APIs. They provide a powerful way to handle asynchronous data flows. However, managing these observables, especially in complex applications, can become challenging. This is where signals come in, offering a simpler and more reactive way to handle data.

The toSignal API: The Hero We All Needed

The toSignal method, a part of Angular's interoperability API, is pivotal in converting observables to signals. It enhances data stream management, making applications more efficient and responsive. The toSignal API accepts various data types and a source, such as data from a REST API, and can also take an initial value, defaulting to 'undefined' if not provided.

A basic example of the toSignal API in use:



import { toSignal } from '@angular/interoperability';

let observable = fetchData('https://my-api.com/data');
let signal = toSignal(observable, []);


Enter fullscreen mode Exit fullscreen mode

In this instance, fetchData is a function that returns an observable from a REST API, which is then transformed into a signal.

Implementing Reactive Primitives for Efficient State Management

Angular's reactive primitives - effects, computed, and signal - play a crucial role in managing state reactively. The focus here is on the computed primitive, which wraps the environment and implements the first reactive primitive. An observable variable is created to hold API response data, which is then converted to a signal.



import { computed, observable, toSignal } from '@angular';

let environment = computed(() => { /* Computed environment code here */ });
let products$ = observable(fetchData('https://my-api.com/products'));
let productsSignal = toSignal(products$, []);

Enter fullscreen mode Exit fullscreen mode




Integrating Signals into Angular Components

To utilize the products signal in a component, Angular 17's new @For loop syntax provides a better alternative to the traditional ngFor. This integration significantly simplifies the component's code and enhances reactivity.



<template>
@for (product of productService.productSignal(); track product){
<!-- Component code here -->
} @empty {
<div>No Products Available</div>
}
</template>

Enter fullscreen mode Exit fullscreen mode




The Benefits of Converting Observables to Signals

The conversion offers several advantages:

  • Simplified State Management: Signals provide a more straightforward approach to managing data streams compared to observables.

  • Enhanced Reactivity: Signals update the UI reactively, ensuring that changes in data are immediately reflected.

  • Performance Improvements: By reducing the reliance on observables in templates, potential performance issues are minimized, leading to faster, more responsive applications.

Conclusion

Converting observables to signals in Angular represents a significant step towards more efficient and reactive web applications. By understanding and implementing this process, developers can optimize the performance and maintainability of their applications. As Angular continues to evolve, embracing these advancements is key to staying ahead in the dynamic world of web development.

Top comments (12)

Collapse
 
pbouillon profile image
Pierre Bouillon • Edited

Angular's new control flows cannot be used like you did, the correct syntax of a @for block is:

@for(product of products; track product.id) {
  <!-- Component code here -->
}
Enter fullscreen mode Exit fullscreen mode

Also, I'm not sure that using toSignal on observables might result in any performance improvements: as you said, it will eagerly subscribe to all observables, leading to more active subscriptions and pipeline being executed.

Collapse
 
desoga profile image
deji adesoga

Thank you for the correction on the syntax, I've made the correction. Cheers!!!

As for the toSignal interop API, there's a potential performance improvement, since we now have access to the different Signal methods and API.

Collapse
 
spock123 profile image
Lars Rye Jeppesen

I can't wait to ditch ZoneJS. It will unlock a lot of awesome improvements (top level await for example), and insane speeds with local change detection. Signals unlock so much good stuff.

I tried removing it (now that Angular 17.1 has an experimental flag that makes it a noOp), but sadly we're relying on Angular/Fire - and that package throws up without ZoneJS.

Great article, cheers

Collapse
 
desoga profile image
deji adesoga

Good to know you're receptive to the concept of Signals. Not many are receptive to it in the community.

As for Angular fire, I hope they provide a Signal compatible update soon. Thank you for reading cheers!

Collapse
 
spock123 profile image
Lars Rye Jeppesen • Edited

I just went zoneless with one of our apps, as the opt-out of zonejs is now possible with Angular 17.1. Small hickups (3rd party stuff) but in general it works well.

I found a workaround for Angular/Fire - just keep zonejs in angular as a polyfill, but opt out in the configuration. This will keep Angular/Fire and Angular/Components happy.

All components have now migrated to input(), it is really beautiful and developer friend as well. Loving how this is going. When we get signal-based components, (hopefully in V18) , performance gains will be on fire, I'm tellin' ya :)

Thread Thread
 
desoga profile image
deji adesoga

I love your enthusiasm towards the adoption of the new updates. Believe me, not many want Signals to get integrated based on most of the interactions I've seen online so far.

I haven't touched Firebase in a long time, but is there a way for you to share the work around. I believe this will be beneficial to many in the community. Perhaps if you could share your integration on Stackblitz.

I'd like to create some content around it. Kindly let me know if you're open to it. Thanks.

Thread Thread
 
spock123 profile image
Lars Rye Jeppesen • Edited

Hi!
It's very simple: do not remove zonejs from the package.json or angular.json of your project.
Just disable zoneJS in the angular app.config file:


import { ɵprovideZonelessChangeDetection as provideZonelessChangeDetection} from '@angular/core';

... in the configuration, add

export const appConfig: ApplicationConfig = {
providers: [
...other providers,
provideZonelessChangeDetection()

Thread Thread
 
desoga profile image
deji adesoga

Awesome. I'll do well to try this out soon. Thank you.

Collapse
 
jangelodev profile image
João Angelo

Deji Adesoga
Nice Tips
Thanks for sharing

Collapse
 
desoga profile image
deji adesoga • Edited

You're welcome! Thank you, João.

Collapse
 
teej107 profile image
teej107

Signals are the hot new Angular feature but I think having the mindset that Observables are too complex and Signals are the fix is a dangerous one. I don't think either is a replacement for the other.

The blanket statement that is relying on Observables in templates reduce potential performance issues is misleading. I'm not sure what Signal specific optimizations Angular is performing under the hood but (to my understanding) a Signal and Observable will only be as performant as their source.

It is also important to know that toSignal may potentially lead to memory leaks depending on if you are using it in a root service or elsewhere since it relies on the injector's context to unsubscribe from the source. This article does a much better job at explaining: Navigating the Nuances of toSignal in Angular: What to Know

Collapse
 
desoga profile image
deji adesoga

Yes Signals have not come replace Observables. However I disagree with the notion that Observables are not complex. They are complex and require a steep learning curve and take time to master, compare to how other frameworks, work.