5

I have an observable that I would like to create a variable with in the ngIf as well as only return false if the value is null (the observable returns a number)

I need to explicitly check for null as my observable can return 0 as a value which triggers the else block.

I have tried the following

*ngIf="(observable$ | async) as obs; obs !== null; esle #elseTemplate"
*ngIf="((observable$ | async) as obs) !== null; esle #elseTemplate"
*ngIf="(observable$ | async) !== null; $implicit = obs; else #elseTemplate"
// this returns the boolean 

My current solution which doesn't seem very elegant is

*ngIf="(observable$ | async) !== null; esle #elseTemplate"
{{ observable$ | async }}

I am using Angular 10.

iamsimonsmale
  • 366
  • 3
  • 14

2 Answers2

5

Usually when I deal with observables in the template like this, I find it far easier to create a single vm$ observable that's built from other observables in the component like this (note, eventually combineLatest will support dictionaries which will mean you won't have to do the map):

vm$ = combineLatest([
    this.observable$,
    this.observable2$
])
.pipe(
    map(([observable, observable2]) => ({
        observable,
        observable2
    }))
);

Then in your dom, you do an ngIf on the vm$ and you can compare the output of your observable directly.

<ng-container *ngIf="vm$ | async as vm">
    <ng-container *ngIf="vm.observable !== null; else #elseTemplate">
    
    </ng-container>
    ...
</ng-container>

EDIT For when combineLatest supports a dictionary the vm$ creation becomes simpler:

vm$ = combineLatest({
    observable: this.observable$,
    observable2: this.observable2$
})
Mathew Berg
  • 28,625
  • 11
  • 69
  • 90
  • 1
    Does this pattern have a name or do you have a link to more information? if you had n more would you do `vm$ = combineLatest([ observable$, obn$ ]) .pipe( map(([observable,obn$]) => ({ observable, obn$ })) );`??? – iamsimonsmale Nov 13 '20 at 12:43
  • 2
    It's brought over from when I used to work with angularJs quite a lot. I recall seeing it on a pluralsight video and a quick google search shows others use it as well. And you're exactly right it would work like that (I've updated my answer). – Mathew Berg Nov 13 '20 at 12:48
0

Another approach I can recommend is the usage of the ngx observe directive from Nils Melhorn https://github.com/nilsmehlhorn/ngx-observe

With this directive you are allowed to define templates for next, loading and even error. The next template also is triggered if a falsy value like your zero is emitted.

*ngxObserve="observable$; let obs; before loadingTemplate; error errorTemplate"
MoxxiManagarm
  • 8,735
  • 3
  • 14
  • 43
  • 3
    I'd be weary of using 3rd party npm packages that are rarely used or maintained. Looking at the github for it the last real code change was 8 months ago. It's not up to date with the latest 2 versions of angular (and several minor ones). – Mathew Berg Nov 13 '20 at 13:02
  • It is just a handy directive, what regular updates do you expect? He could also copy the directives code tho. – MoxxiManagarm Nov 13 '20 at 14:32