Angular 16 Preview: TakeUntilDestroyed

Angular 16 will be released next week, and this new version will be big. I will cover most of the new features of Angular 16 for the next few days.

One of the simple but handy features shipped with Angular 16 is a new operator for RxJs Observables: takeUntilDestroyed.

We have covered several techniques to automatically unsubscribe from Observables in this newsletter.

takeUntilDestroyed will make all of it easier than ever:

And that’s it! That one operator will take care of automatically unsubscribing from data$ when the component/pipe/directive using it is destroyed.

Signals will be the most significant addition to Angular 16 (as a developer preview – for now), and as a result, I’m about to launch a short course on Signals. If you’re interested in beta-testing that course (for free!), please respond to this email to let me know.

RxJs takeUntil and takeWhile operators

Our Rxjs operators of the week are takeUntil and takeWhile. These operators are the opposite of skipWhile covered last week: They let the values from the source Observable pass through until a condition is met.

takeUntil is based on a second Observable and stops emitting values when that second Observable emits for the first time, as illustrated in this marble diagram:

takeWhile is very similar but uses a predicate instead of an Observable to decide when to stop emitting from the source Observable:

The primary use case for takeUntil with Angular is to automate unsubscriptions from Observables, even though I recommend less verbose approaches to automating unsubscriptions, such as using the async pipe :

The above code uses a subject to emit a value when the component gets destroyed, thanks to the ngOnDestroy lifecycle hook. Then, that same subject is used by takeUntil to complete the source Observable.

Here is a different example of takeUntil in action on Stackblitz.

RxJs skipWhile operator

Our RxJS operator of the week is skipWhile. This operator will ignore values emitted by an Observable as long as a given condition is true.

Its marble diagram looks like this:

The above example shows us that as long as the emitted values are less than 5, they get skipped.

What are some everyday use cases forĀ skipWhile? Here is an example where I want to wait for the user to type at least two characters in a form input before we start filtering (an addition to last week’s startWith example):

That way, the filter$ observable starts emitting values only when the source FormControl value has a length of at least two characters, which results in the following behavior:

This can be used to delay querying a server-side API with HTTP to start filtering only once we have enough meaningful data. This is somewhat similar to what can be done with the debounceTime operator.

You can see the complete example here on Stackblitz.

RxJs startWith operator

startWith is an operator that does something straightforward: It takes an existing Observable and makes it emit a default value immediately.

Its marble diagram looks like this:

What are some everyday use cases for startWith? Here is an example where I want to display a loader while data is being loaded from a service:

The loading property is used to decide when to show/hide a loader. This observable would first emit { data: null, loading: true } then the actual data with loading: false.

You can see the complete example here on Stackblitz ( I had fun with Typescript, the async pipe, and generics in that example, too).

A more complex example in this tutorial is Dynamic filtering with RxJs and Angular forms. I describe how to create a text input used to filter a list of states as follows:

We need startWith in that scenario to start the filtering feature before the user has typed anything in the text input. That’s one of the most common use cases for the startWith operator.

RxJs share and shareReplay operators

Last week, we covered the difference between hot and cold Observables in RxJs.

Today, let’s talk about how we can make a cold Observable hot. Why would we want that? Say our Observable is an HTTP request we want to trigger before any component subscribes to it. We saw that Observables from the HttpClient are cold, meaning that they only start fetching data when a subscriber comes over.

By making the Observable hot, the HTTP request would get triggered immediately. The share operator would do exactly that for us:

Under the hood, share turns our Observable into a Subject, which can handle multiple subscribers and is hot by default.

The only problem with the above example is that the data could be emitted before any subscriber gets the chance to subscribe to that new hot Observable.

As a result, it makes more sense to use shareReplay instead as it’s going to replay the latest value(s) to any new subscriber (just like a ReplaySubject):

This code is much better because:

  • The request is going to fire instantly before any subscription happens
  • Any future subscriber will receive the same data from that original request instead of firing a new request.

You can look at this blog post for an illustration of the above operators with a code example.

How to decide which RxJs operator to use?

There are more than 120 operators in RxJs, and with so many options, it can be challenging to decide which one we should use. We covered a few of them in this newsletter so far and mentioned websites such as Rxmarbles to learn more about these operators.

Luckily, Rxjs.dev has an interesting feature called the operator decision tree. This tool asks a few questions about what we’re trying to do and ends up suggesting one operator that answers that need.

It uses a wizard-style approach:

The tool is excellent and does save a lot of time researching operators in the documentation. I found some scenarios where it suggests deprecated options. Still, each deprecated feature has a link to its replacement, so it’s easy to find the actual operator to use from there.

RxJs debounceTime operator

This week’s RxJs operator is very commonly used for form validation: debounceTime.

debounceTime is going to delay emitted values for a given amount of time (in milliseconds) and emit the latest value after that period has passed without another source emission. I know it’s not super easy to describe with words.

A marble diagram for debounceTime looks like this:

In the above example, the values 2 – 3 – 4 – 5 are emitted less than ten milliseconds from one another, so they get dropped. Only five gets emitted 10 ms later.

Why is that useful for form validation? Because we usually want to wait for the user to finish typing something before triggering some asynchronous validation. For instance, if we validate a street name, it makes sense to wait for the user to stop typing for a while instead of sending HTTP requests to an API every time a new keystroke happens, which would flood the server with useless validation requests.

Using our credit card demo from yesterday, here is a different Stackblitz example where I debounce the output for 400 ms. This is the result:

You can see that the debounced value gets displayed once I stop typing for 400 ms. So that’s how I used that operator:

And then display the results side by side in my HTML template as follows:

Usually, 300 to 400 ms is an excellent spot to debounce user input, but you can try different values and see what works best.

If you want to dive deeper into asynchronous form validation, this tutorial should help: How to write async form validators with Angular?

RxJs distinctUntilChanged operator

This week, our RxJs operator of choice is distinctUntilChanged, another of these few operators with a name that is explicit enough.

distinctUntilChanged ignores unchanged values that get emitted several times:

This operator is beneficial when using RxJs to filter out data based on filters selected by the end user in the UI. For instance, it’s a way to ensure that we only trigger a data update (such as an HTTP request) when the filters have changed.

A notable feature is that you can pass a custom comparison function as a parameter to determine how to compare those values. Otherwise, the operator uses === as a default comparison, which is acceptable for basic types but not for comparing objects unless you want to compare references.

RxJs forkJoin operator

Our weekly RxJs operator is forkJoin. This operator can be applied to any number of Observables. When all these Observables complete, forkJoin emits the last value from each one of them.

A common use case for forkJoin is when we need to trigger several HTTP requests in parallel with the HttpClient then receive all of the responses at once in an array of responses:

The critical feature here is that those requests happen simultaneously, not one after the other (better performance), yet we receive the data when both have completed, which is convenient.

Another interesting syntax for forkJoin is to pass an object instead of an array as follows:

Here is a complete example of forkJoin in action.

As a reminder, my 2-hour RxJS workshop from ng-conf 2022 is also available on Youtube for free!

RxJs withLatestFrom operator

Our weekly RxJs operator is withLatestFrom, a rare example of an operator with a name that says it all.

Here’s the marble diagram for withLatestFrom:

This operator takes two or more Observables and turns them into one single Observable that emits a new value whenever the source Observable emits something new.

The important thing to note here is that only one Observable triggers updates in the output Observable. As a result, withLatestFrom is a great option when you want a user action to trigger an update in the user interface (think about data table filters, inter-connected dropdowns, etc.)

You can see a live code example here (including comments that explain the thought process) with two dropdowns that depend on one another. A selection in the first dropdown impacts the values displayed in the second one (selecting a continent filters out the countries shown in the second dropdown:

If you want a deeper dive, I have this complete tutorial on using withLatestFrom alongside other operators to implement dynamic filtering in a component.

And for even more RxJs content, my 2-hour RxJS workshop from ng-conf 2022 is now available on Youtube for free!