简体   繁体   中英

Angular async pipe in *ngIf - handle 0 value

I have the following html snippet:

<div *ngIf="calculatedValue$ | async as calculatedValue">
  {{calculatedValue}}
</div>

But if the emitted value of calculatedValue$ is 0 (type = number), the div won't be displayed in the DOM.

What is the correct way to showing it? Maybe in the way that a non null check gets added to the *ngIf.

As you already suggested; it's type need to be number.

typeof (calculatedValue$ | async) === 'number'

Or simply not null

(calculatedValue$ | async) !== null

Instead of *ngIf, just use *ngLet. There are multiple implementations of it on the web, for example within https://github.com/ngrx/component-builds . I honestly don't understand why this is still not a part of angular core.

How mention @joosep parts in a comment, you can assign the value to an object, for example this code shows a progress bar even when its value is 0

component.ts

progress$ = new BehaviorSubject<number>(0);

component.html

<ng-container *ngIf="{ value: progress$ | async } as progress">
    <app-progressBar
       [value]="progress.value"
    ></app-progressBar>
</ng-container>

This is an expected behaviour. The following are all the values that javascript currently translates to false:

if (false)
if (null)
if (undefined)
if (0)
if (NaN)
if ('')
if ("")
if (``)

https://stackblitz.com/edit/async-pipe-jghgvc?file=app%2Fasync-pipe%2Fasync-pipe.component.html

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: promise | async } as calculatedValue">
    <div>{{ calculatedValue.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.

This issue is being tracked here: https://github.com/angular/angular/issues/15280

One of the workarounds implemented using your use case would look like this:

 <div  *ngIf="{ calculatedValue: calculatedValue$ | async } as context">
    {{ context.calculatedValue }}
 </div>

The other way which is the most likely, the only way right now is to subscribe it in your .ts component and then use that property to check for null values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM