Signals: computed()

After introducing how to create Signals and how to update them, let’s take a look at one more exciting feature that helps replace the need for RxJs Observables.

How to emit a new Signal value when one or more Signals get updated? That’s what computed() does. In my Signals course, I illustrate computed() with the following example:

In the above code, this.rates() and this.currency() are two different Signals. this.rates() emits up-to-date exchange rates for all currencies in the world. this.currency() emits the current currency selected by the user.

computed() takes a function as a parameter. The function returns the computed value from my two Signals; in this case, the up-to-date exchange rate for the current currency. If the exchange rates or the currency get updated, this computed Signal will emit an updated value automatically.

This is somewhat similar to combining several Observables and using switchMap or combineLatest to get a customized result. It’s a lot easier with Signals (one line of code!).

Ng-conf 2023 is coming up soon

If you’re considering attending a tech conference and have never done so before, I would suggest going to ng-conf 2023 in Salt Lake City this June (also available online if you can’t travel to beautiful Utah):

You know what I’m talking about if you have attended ng-conf before. It is the largest Angular conference in the world, the Angular team is there, and the best Angular speakers are on stage (I can say so because I’m not speaking this year – but I’m going anyways!).

I have learned so much at ng-conf in the past. Several tips and tricks of this newsletter were gathered at the conference. It is safe to say that this conference helped me get where I am today as an Angular coach and consultant. The organizers go above and beyond to ensure everyone is welcome at ng-conf; the experience is always a blast.

After all, they’ve even brought a Back to the Future Delorean and a Daft Punk tribute concert to the event in the past few years – to name a few examples:

If you’re attending the conference, please let me know and come say hi. It’s always a pleasure to meet my readers. And if you’re not going… You’ll still get updates from the conference in this newsletter!

Anti-pattern series: Using too many services

While services and dependency injection are good, just like many good things in life, they can be over-used and become somewhat of an anti-pattern.

Why? Because of how change detection works in Angular. Angular has two modes for change detection: The default mode and the onPush mode. onPush is an optimization that works if and only if you’re using input-driven components, also known as presentation components.

In other words, whenever you inject a service into a component, you prevent that component from using the optimized onPush change detection mode. This is one of the reasons best practices recommend sticking with container components (service-driven components tied to specific use cases) and presentation components (input-driven ones that can be used and reused as they’re not connected to any service – and any business logic).

The more presentation components you create, the more reusable your code is, and the more change detection can be improved. The next time you inject a service in a new component, think again: Could I pass that data as @Input(s) instead of injecting a service?

If so, congratulations: You just prevented your presentation component from falling into this anti-pattern.

RxJs TapObserver

In my last post, I covered how we can define multiple callback functions when subscribing to an Observable (next, error, complete). I mentioned that those callbacks are available when we call the subscribe() method, which goes against our philosophy of avoiding subscriptions as much as possible because they can lead to memory leaks.

In previous newsletters, I covered how the tap operator can help avoid subscriptions by “spying” on an Observable.

Well, tap is a simple gift that keeps on giving. The operator supports an TapObserver interface that can be used instead of the callback function we used in our earlier examples:

As a result, we can register several side effects in our code based on any of these notifications as follows:

Most of these notifications are explicit in what they do, but let’s document all six of them for the sake of clarity:

  • next: Invoked whenever the Observable receives new data
  • error: Invoked whenever an error occurs within the Observable
  • complete: Invoked when the Observable completes and stops emitting any new values.
  • subscribe: Invoked whenever a new subscriber subscribes to the Observable
  • unsubscribe: Invoked whenever a subscriber unsubscribes from the Observable
  • finalize: Invoked whenever the Observable is done, either because of an error, of completion, or unsubscription. It’s like a catch-all notification to mark the end of an Observable.

You can see an example of such TapObserver in action here on Stackblitz.

RxJs subscribe callback functions

At this point, it is safe to assume that most Angular developers know about the following syntax. That’s how we subscribe to an Observable to receive its data:

If you’ve been reading this newsletter for long enough, you already know that there are better ways to subscribe to Observables and that there are no excuses for not using these techniques.

That said, it’s always good to know about all our available options. So here is another possible syntax:

The above syntax registers three different callback functions:

  • The first one is the same as in our first example – this is where the Observable data goes.
  • The second one is an error handler. Any exception thrown by the Observable would get caught by that callback.
  • The third callback function is invoked when the Observable completes, which means it won’t emit any more value.

Note that while that syntax still works (for now), it has been deprecated in favor of a more explicit syntax, where an object is passed. Each callback is attached to a named property, making the purpose of these callbacks more obvious:

Skeleton loaders with Angular

Skeleton loaders are grey-shaded shapes that indicate when a part of the screen is loading. Here is an example of skeleton loaders for Facebook:

ngx-skeleton-loader is a small component library that does just that. It gives us access to different skeleton loaders ready to be used in our applications:

What’s nice about that library is that we can customize different aspects of the skeletons, such as animations and colors. You can find some live examples here.

If you want to explore skeleton loaders for your application, feel free to look at my popular tutorial: How to use a skeleton loader with Angular?

The tutorial has several code examples that can be used as-is.

Two ways to update Angular Signals

Yesterday, I wrote about some best practices around exposing a Signal in our Angular applications. Let’s now take a look at the two different ways a Signal can be updated.

set()

The easiest way to update a Signal is the set() method. Nice and easy for basic data types such as strings or booleans:

update()

When the new value of a Signal depends on its previous value, update() is the best method to use. This is the ideal method for a counter, for instance:

Here is how to increment the counter based on its current value:

TL;DR

  • When you need to update a simple value (string, number, boolean), use set().
  • If that new value is based on the previous one, use update() instead of set()

Anti-pattern series: Not unsubscribing from Observables

We covered this in our newsletter before: Observables can cause memory leaks if we don’t unsubscribe from them.

Before Angular 16, there were a few different techniques available to unsubscribe automatically, the best of those being the async pipe (and yes, it’s possible to use the async pipe 100% of the time if you use the tricks highlighted here – no excuses).

With Angular 16, things are even better, as you can use the new takeUntilDestroyed operator as follows:

But here’s my million-dollar tip for today: Instead of using takeUntilDestroyed in your components, use it in the services that expose such Observables:

That way, whether you use an async pipe or not, your components are covered. That’s one of the nice things about Observables: We can change them whenever and wherever we want using pipe(), including in our services – so that all subscribers benefit from that change downstream.

mergeMap RxJs operator

A few months back, we covered the switchMap operator from RxJs. Today, let’s look at a similar operator called mergeMap:

The marble diagram isn’t as obvious as it is for other operators, so let’s clarify what mergeMap does:

  • It takes values from an observable and maps them to another observable
  • Then it allows us to combine the values from both observables into one new observable

What’s a real-life use case for mergeMap?

Let’s say you want to display a list of products with their associated categories. The product information is stored in one API endpoint, and the category information is stored in another API endpoint. To display the list of products with their categories, you need to make a separate API call for each product to retrieve its category information.

You can use mergeMap to combine the two API calls and merge the results into a single stream of data (product + category).

How is it different from switchMap?

mergeMap differs from switchMap in two important ways:

  1. switchMap only returns the data from observable #2 – mergeMap returns data from both observable #1 and #2 and allows us to combine that data any way we want
  2. switchMap cancels observable #2 whenever observable #1 emits a new value, then re-creates another observable #2. mergeMap doesn’t do that.

In other words, switchMap is perfect when we want to chain asynchronous actions such as “user selects a new filter, then we request new data according to that filter” because if the user changes that filter again, we want to cancel the previous request and start a new one.

Angular at Google I/O

This a very short post today as I spent most of my day at Google I/O, the annual conference where Google announces all sorts of updates ranging from AI to Android to Web, including Angular.

The Angular team had a few talks on Angular 16, all of which are now available on YouTube so that you can watch them too:

They also published a list of shorter videos (2 to 6 minutes) on Angular 16.