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.
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