У мене є Angular компонент, який отримує послугу CatalogService
вводиться:
export class CatalogListComponent implements OnInit {
catalog$: Observable<MovieResponseItem[]>;
constructor(private catalogService: CatalogService) {}
ngOnInit() {
this.catalog$ = this.catalogService.userCatalog;
}
}
Ця послуга повертає Observable<MovieResponseItem[]>
на власність userCatalog
:
@Injectable()
export class CatalogService {
get userCatalog(): Observable<MovieResponseItem[]> {
return this._userCatalogSubject.asObservable();
}
}
The MovieResponseItem
це просто простий інтерфейс:
export interface MovieResponseItem {
title: string;
}
Тепер я хочу повторити елементи та відобразити анімацію завантаження, поки каталог запитує базову службу щодо даних (це займає деякий час) - це працює. Ось шаблон, що використовується:
<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>
Це, очевидно, відображає шаблон #loading, поки асинхронізація очікує даних. Якщо спостережуване повертає дані, воно перебирає значення каталогу.
Але зараз я хочу розділити це на таку поведінку:
- поки ми чекаємо даних, відобразимо анімацію завантаження
- якщо ми отримали відповідь служби, а повернутий список порожній, покажіть інформаційний текст (наприклад, "ваш каталог порожній") і не повторюйте (оскільки даних немає)
- якщо ми отримали відповідь служби, а повернутий список має значення, повторіть елементи (як у поточному стані)
Як я можу це отримати? З того, що я читав у схожих дописах, цього ніхто не намагався досягти (або я його не знайшов).
Дуже дякую!
Відповіді:
12 для відповіді № 1 <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>
Це повинно зробити трюк. Краще використовувати якомога менше асинхронних каналів і просто оголосити це "як" змінною шаблону, яку можна використовувати де завгодно. В іншому випадку потік буде виконуватися один раз за асинхронний канал, що є поганою практикою і може створити непотрібні виклики http, якщо це підтримується http.
0 для відповіді № 2
хммм .. https://github.com/angular/angular/issues/14479
Просто додайте ще один стан ngIf - 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>