Angular 4 async with loading and rendering when empty

I have an Angular component that receives the CatalogService service:

 export class CatalogListComponent implements OnInit { catalog$: Observable<MovieResponseItem[]>; constructor(private catalogService: CatalogService) {} ngOnInit() { this.catalog$ = this.catalogService.userCatalog; } } 

This service returns the property Observable<MovieResponseItem[]> on userCatalog :

 @Injectable() export class CatalogService { get userCatalog(): Observable<MovieResponseItem[]> { return this._userCatalogSubject.asObservable(); } } 

MovieResponseItem is just a simple interface:

 export interface MovieResponseItem { title: string; } 

Now I want to iterate over the elements and display the loading animation, while the directory is requesting a basic service for the data (which 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 explicitly displays the #loading pattern while async is waiting for data. If the observed data is returned, it is repeated over the directory values.

But now I want to separate this from this behavior:

  • while we wait for the data, display the loading animation
  • if we have a response from the service and the returned list is empty, show the information text (for example, "your directory is empty") and do not repeat (since there is no data)
  • if we have a response from the service, and the returned list has values, iteration of the elements (as in the current state)

How can I achieve this? From what I read in similar posts, no one tried to achieve this (or I did not find it).

Thanks a lot!

+5
source share
2 answers
  <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> 

gotta do the trick. It’s best to use as few asynchronous pipes as possible and simply declare it β€œas” a template variable that you can use anywhere. Otherwise, the thread will be executed once in one asynchronous channel, which is bad practice, and adn can create unnecessary HTTP calls if it is HTTP support.

+4
source

hmmm .. https://github.com/angular/angular/issues/14479

Just enter another ngIf condition - else.

 <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> 
0
source

Source: https://habr.com/ru/post/1272140/


All Articles