angularpromiseangular-promise

How to do a ngIf based on a promise in angular?


I'm trying to do a ngIf where the result is depending on a promise.

The template

<div>
  <select [(ngModel)]="carValue" name="carName">
    <option value="renault">Renault</option>
    <option value="bmw">Bmw</option>
  </select>
  <p *ngIf="isDisplayed()">Good choice!</p>
</div>

So far, the function isDisplayed is

isDisplayed() {
  return this.carValue === 'bmw';
}

But I'd like it to be asynchronous. Something like

isDisplayed() {
  return this.getBestChoice().then((result) => result);
}

getBestChoice() {
  // fake http call
  return new Promise((resolve) => {
    setTimeout(() => resolve('bmw'), 3000);  
  });
}

Obviously it won't work. I have ideas how to implement this but not sure it is clean.

Here is a punker.


Solution

  • Why not go with Observables, it's the Angular way. You can just set one as a public property and run it throught AsyncPipe which'll handle sub/unsub and change detection triggering for you.

    import { Component } from '@angular/core';
    import { Observable } from 'rxjs/Observable';
    import { timer } from 'rxjs/observable/timer';
    import { map, share, tap } from 'rxjs/operators';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
      carValue = '';
      showCongrats$: Observable<boolean>;
      check() {
        // fake API call
        this.showCongrats$ = timer(1000).pipe(
          map(() => 'bmw'), // "API" says bmw rocks
          tap(console.log),
          map(bestCar => this.carValue === bestCar),
          share() // so multiple async pipes won't cause multiple API calls
        );
      }
    }
    

    Template:

    <div>
        <select [(ngModel)]="carValue" (change)="check()">
        <option value="">Choose</option>
        <option value="renault">Renault</option>
        <option value="bmw">Bmw</option>
      </select>
        <p *ngIf="showCongrats$|async">Good Choice!</p>
        <p *ngIf="carValue && (showCongrats$|async) === false">Not the Best Choice!</p>
    </div>
    

    Working stackblitz: https://stackblitz.com/edit/angular-cxcq89?file=app%2Fapp.component.ts