I have an Angular component that gets a service CatalogService
injected:
export class CatalogListComponent implements OnInit { catalog$: Observable<MovieResponseItem[]>; constructor(private catalogService: CatalogService) {} ngOnInit() { this.catalog$ = this.catalogService.userCatalog; } }
This service returns an Observable<MovieResponseItem[]>
on property userCatalog
:
@Injectable() export class CatalogService { get userCatalog(): Observable<MovieResponseItem[]> { return this._userCatalogSubject.asObservable(); } }
The MovieResponseItem
is just a simple interface:
export interface MovieResponseItem { title: string; }
Now I want to iterate the items and display a loading animation while the catalog queries the underlying service for data (that takes some time) - this works. This is the template used:
<div *ngIf="(catalog$ | async)?.length > 0; else loading"> <ng-container *ngFor="let item of catalog$ | async"> <div>{{item.title}}</div> <ng-container> </div> <ng-template #loading>loading animation...</ng-template>
This obviously displays the #loading template while the async is awaiting data. If the observable returns data, it iterates over the catalog values.
But now I want to separate this into this behaviour:
How can I achive this? From what I read on similiar posts nobody tried to achieve that (or I did not find it).
Thanks a lot!
<div *ngIf="catalog$ | async as catalog; else loading"> <ng-container *ngIf="catalog.length; else noItems"> <div *ngFor="let item of catalog">{{item.title}}</div> </ng-container> <ng-template #noItems>No Items!</ng-template> </div> <ng-template #loading>loading animation...</ng-template>
This should do the trick. Better to use as few async pipes as possible and just declare it "as" a template variable you can use where ever. Otherwise the stream will be executed once per async pipe which is a bad practice and could create unneeded http calls if this is http backed.
*edit for the syntax error
hmmm.. https://github.com/angular/angular/issues/14479
Just throw in another ngIf - else condition.
<div *ngIf="(catalog$ | async); else loading;"> <div *ngIf="catalog$.length == 0; else empty;"> <ng-container *ngFor="let item of catalog$ | async"> <div>{{item.title}}</div> <ng-container> </div> <ng-template #empty>empty animation...</ng-template> </div> <ng-template #loading>loading animation...</ng-template>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With