Image for post
Image for post

Handling Falsy Values Emitted from Observables in Angular

Preston Lamb
Sep 21 · 4 min read

In the last year or so, I’ve been fully embracing reactive programming in my Angular apps. That means goodbye subscribe and hello async pipe! It’s been great, but there have been a couple times where the async pipe, in conjunction with the *ngIf structural directive, have not worked as I needed them to. The issue arises when the emitted value from the observable is falsy. When the emitted value is falsy, the *ngIf doesn’t output the content on the screen. I understand why that happens, but many times the falsy value is a valid result and should be displayed. In this post, we’ll cover an easy way to still use the async pipe and *ngIf while still outputting falsy values.

The Issue Explained

Recently, I was working on an application at work where we needed to output the emitted value of an observable. The value was a number with zero being a valid result. We also wanted to display a loading spinner while waiting on data from the API. We did that with the *ngIf structural directive and the else option that goes along with it. Here’s a brief sample of what that looked like:

<div 
*ngIf=”observableValue$ | async as value; else backupLoader”>
{{ value }}
</div>

This worked in most situations. Before the observable emitted the response from the API, the loader would show up on the screen. As soon as the value came back, it replaced the loader. The only time it didn’t work was when the emitted value was 0. The loader would stay on the screen and 0 would never show up. The reason for that is that 0 is a falsy value, and thus the *ngIf never stopped showing the loader.

One solution to get around this was to convert the returned value to a string and not a number. I didn’t want to have to alter the value though to get my desired result. I turned to Twitter for a little bit of help and came up with the following solution.

Wrapping Observable Values in Objects

The easiest way to solve this issue is to turn the emitted value from the observable into an attribute on an object. You can do this in the component class file, or directly in the HTML. I’m going to do this directly in the HTML. Here’s what that looks like:

<ng-container 
*ngIf=”{ observableValue: observableValue$ | async } as data”>
<div>{{ data.observableValue }}</div>
</ng-container>

What we’ve done here is subscribed to the observable with the async pipe, and put the value into the observableValue attribute of an object. Notice the curly brackets inside the *ngIf structural directive. We then use the as syntax, which renames the variable for use in the template. Inside the double curly brackets, the result is output by accessing the observableValue attribute of the data object.

The *ngIf directive on the ng-container element will now always evaluate to true because we have created that object. So, no matter what value is emitted from the observable, we will output it to the screen.

What About the Loader?

Wrapping the observable in an object was nice, and now we can output falsy values. But if we stop with the example in the previous section we’ll have lost our loader element. So the last part to figure out is how to combine wrapping the observable in an object with showing the loader element before the data is loaded. We can do that by using a second *ngif inside the ng-container, like this:

<ng-container 
*ngIf=”{ observableValue: observableValue$ | async } as data”>
<div *ngIf=”
data.observableValue !== null &&
data.observableValue !== undefined;
else backupLoader”
>
{{ data.observableValue }}
</div>
<ng-template #backupLoader>
<app-loader></app-loader>
</ng-template>
</ng-container>

The ng-container is the same here as it was before. But the div that wraps the data.observableValue output now has a new *ngIf placed on it. The two checks added here are that the observableValue attribute value is not null or undefined. If the value is null or undefined, then the loader is shown. Otherwise, the value is output (including if it’s falsy).

Conclusion

I have been working with Angular for a long time at this point, and am really bummed that I hadn’t figured this out years ago. This is a great way to output falsy values while using the async pipe and the *ngIf structural directive. I will be using this a lot going forward, and hope that this will be useful for you as well.

I also want to give credit to Maxime Robert for writing this great article on dev.to and to Aaron Frost for the suggestion on Twitter.

EnterpriseNG is coming

EnterpriseNG is a two-day conference from the ng-conf folks coming on November 19th and 20th. Check it out at ng-conf.org

ngconf

The World’s Best Angular Conference

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store