Angular 4异步加载和空时显示
Posted
技术标签:
【中文标题】Angular 4异步加载和空时显示【英文标题】:Angular 4 async with loading and display when empty 【发布时间】:2018-03-08 03:23:24 【问题描述】:我有一个 Angular 组件,它获得了 CatalogService
injected 服务:
export class CatalogListComponent implements OnInit
catalog$: Observable<MovieResponseItem[]>;
constructor(private catalogService: CatalogService)
ngOnInit()
this.catalog$ = this.catalogService.userCatalog;
此服务在属性userCatalog
上返回Observable<MovieResponseItem[]>
:
@Injectable()
export class CatalogService
get userCatalog(): Observable<MovieResponseItem[]>
return this._userCatalogSubject.asObservable();
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 模板。如果 observable 返回数据,它会遍历目录值。
但现在我想把它分成这种行为:
在等待数据时,显示加载动画 如果我们有来自服务的响应并且返回的列表为空,请显示信息文本(如“您的目录为空”)并且不要迭代(因为没有数据) 如果我们有来自服务的响应并且返回的列表有值,则迭代项目(与当前状态一样)我怎样才能做到这一点?根据我在类似帖子上阅读的内容,没有人试图实现这一目标(或者我没有找到)。
非常感谢!
【问题讨论】:
您可以在您的 ngFor 容器下方添加另一个<ng-container *ngIf="catalogService.userCatalog.length == 0"> <div>your catalogue response is empty</div> <ng-container>
。
【参考方案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 调用。
*修改语法错误
【讨论】:
感谢您的回答!不幸的是,这从不显示加载模板,但在等待 Observable 答案时总是显示 noItem。 结构和范围必须像我布置的那样,否则将无法正常工作。加载需要在 ngIf 上的异步之外,并且 noItems 需要在异步范围内但在 catalog.length 范围之外 我也不确定您的 catalog$ observable 的源主题是什么,但如果它是一个行为主题,那么这将永远不会“加载”,因为该值总是立即存在。如果是这种情况,那么您需要将其初始化为 null 而不是 [] 因为 [] 是“真实的”,而 null 是虚假的 明白了,可能我的 observable 是问题所在。正如您所说,我使用与.asObservable()
一起使用的BehaviorSubject<MovieResponseItem[]>
。我会尝试重构它。
您仍然可以将其初始化为 null,因为默认情况下,打字稿中的每个值都可以为空。您还可以添加 .filter(v => !!v) 以仅传递非空值,这为您提供两种主题类型的时间优势【参考方案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>
【讨论】:
catalog$ 是一个列表的可观察对象,因此它永远不会有长度 谢谢,正如在另一个答案中看到的那样,我的catalog$
永远不会为空(目前,会调整它),因此永远不会显示 laoding 动画。很好的链接问题!以上是关于Angular 4异步加载和空时显示的主要内容,如果未能解决你的问题,请参考以下文章
如何仅在 Angular 的某些页面上显示标题组件(现在它仅在重新加载时显示)
Angular 2 - 当(observableData | async)尚未解决时显示加载信息
如何在应用程序首先加载而不是Angular 5中的appComponent时显示登录组件