Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

392
Views
Angular display template if observable is falsey with async pipe

I have an API call that may return some data or may return something falsey if no data exists. If there is data, I want to tap out of the stream and do some side effects, but if falsey, I want no side effects to happen but still display my template code.

I am using an async pipe to get that data in the template, but if the data is falsey, it will not display.

I have seen the technique to wrap the ngIf with an object so it evaluates to truthy, but it doesn't seem the correct solution for my code.

My template:

<form *ngIf="loadedData$ | async">
  ...
</form>

My class:

loadedData$: Observable<boolean>;

ngOnInit(): void {
  this.loadedData$ = this.getCurrentBranding().pipe(
    tap(branding => {
      if (branding) {
        // Do side effects
      }
    }),
    // current hack to make the template show
    map(() => true)
  );
}

private getCurrentBranding(): Observable<Branding> {
  // API call, may return an object, or null
}
over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

You can always try to keep it as semantic as possible. Your approach using map is not a bad idea, it's just that you actually lose the access to your data. It's probably better to split it up in two Observables:

readonly data$: Observable<BrandingData> = this.getCurrentBranding().pipe(
  tap((branding) => { /* Do side effects */ }),
  shareReplay({ refCount: true, bufferSize: 1 })
);

readonly loadingData$: Observable<boolean> = this.data$.pipe(
  mapTo(false),
  startWith(true)
);

You can then show your form by checking if the data is being loaded:

<form *ngIf="(loadingData$ | async) === false"></form>

What happens here is that by subscribing to the loadingData$ in the template, actually also subscribes to the data$ osbervable, which will trigger the API request. By using shareReplay, you make sure that this request is only done once on every subscribe.

over 4 years ago · Santiago Trujillo Report

0

the "typical" is use an object as "if" in the way

<!--see that the if is always "true" -is an object- -->
<form *ngIf="{response:loadedData$ | async} as res">
   <!--you has the response in res.response-->
   <ng-container *ngIf="res.response===false">
      the result of the call is false
   </ng-container>
   <ng-container *ngIf="res.response!===false">
    {{res.response|json}}
   </ng-container>
</form>
over 4 years ago · Santiago Trujillo Report

0

I've been getting in the habit of having a single observable for my component that merges multiple streams, combining them into one state. Usually this involves the scan operator, but in this case it's not necessary (though maybe you want to merge in these side effects too).

In the code below getCurrentBranding will execute when it is subscribed to by the async pipe in the component. To prevent multiple executions you can have one root element that uses Angular's as expression to convert the emission into a template variable. Alternatively, you could use shareReplay.

The startWith operator is used to provide an initial value, so the root element will always be displayed. The form will initially be hidden until the result is returned from the api. The data will come from the same observable and access from the template variable created at the root element.

this.state$ = this.getCurrentBranding().pipe(
  tap(branding => { /* Do side effects */ ),
  map(data => ({ data, isLoaded: true}),
  startWith(({ data: [], isLoaded: false})
);
<ng-container *ngIf="(state$ | async) as state">
  <form *ngIf="state.isLoaded">
    <!-- ... -->
  </form>
  <ol *ngFor="let o of state.data">
    <!-- ... -->
  </ol>
</ng-container>
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!