Angular 4异步加载和空时显示

Posted

技术标签:

【中文标题】Angular 4异步加载和空时显示【英文标题】:Angular 4 async with loading and display when empty 【发布时间】:2018-03-08 03:23:24 【问题描述】:

我有一个 Angular 组件,它获得了 CatalogServiceinjected 服务:

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

此服务在属性userCatalog 上返回Observable&lt;MovieResponseItem[]&gt;

@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 容器下方添加另一个 &lt;ng-container *ngIf="catalogService.userCatalog.length == 0"&gt; &lt;div&gt;your catalogue response is empty&lt;/div&gt; &lt;ng-container&gt; 【参考方案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&lt;MovieResponseItem[]&gt;。我会尝试重构它。 您仍然可以将其初始化为 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 的某些页面上显示标题组件(现在它仅在重新加载时显示)

如何在Angular2中使用导航进行路由时显示加载屏幕?

Angular 2 - 当(observableData | async)尚未解决时显示加载信息

如何在应用程序首先加载而不是Angular 5中的appComponent时显示登录组件

java如何实现二级树形菜单动态显示。要求加载页面时显示一级,点击一级菜单再去数据库查找出二级菜单

日期选择器仅在聚焦时显示错误