在模板中使用带有异步管道的 Observable 时显示加载

问题描述 投票:0回答:4

情况:我正在使用 FirebaseObjectObservable 来填充我的 Ionic 2 (rc0) 模板。 模板代码:

<ion-card-content>
  <p>{{(course | async)?.description}}</p>
  <br>
  <h2>Learning Objectives</h2>
  <ul>
    <li *ngFor = "let objective of (course | async)?.objectives">{{objective.text}}</li>
  </ul>
  <h2>Takeaway</h2>
  <ul>
    <li *ngFor = "let takeaway of (course | async)?.takeaways">{{takeaway.text}}</li>
  </ul>
</ion-card-content>

TS代码:

this.course = this.af.database.object('/bbwLocations/courses/' + courseId); 

this.course 是一个 Firebase 对象 Observable。一切正常!但是每当我进入模板时,就会出现空白无数据的闪光。然后所有的数据都跳出来了!非常不友好。所以我想使用某种预加载策略。但是由于这里没有 TS 逻辑。一切都在模板级别使用异步管道进行控制。在这种情况下我将如何添加负载?

angular ionic2 observable angularfire2
4个回答
14
投票

也许有点晚了,但万一有人想知道如何管理这个…… 使用模板怎么样?

例如,您可以使用类似的东西:

<ion-card-content *ngIf='(course$ | async) as course; else loading'>
  <p>{{course.description}}</p>
  <br>
  <h2>Learning Objectives</h2>
  <ul>
     <li *ngFor = "let objective of course.objectives"> 
         {{objective.text}}</li>
  </ul>
  <h2>Takeaway</h2>
  <ul>
     <li *ngFor = "let takeaway of course.takeaways"> 
         {{takeaway.text}}</li>
  </ul>
</ion-card-content>

<ng-template #loading>
  Loading stuff...
</ng-template>

所以你的离子卡内容将被隐藏,显示#template,直到加载异步管道。


12
投票

你可以这样做:

<style>
  pre {
   color: orange;
   // or whatever you want
  }
</style>
<ion-card-content>
  <p>{{(course | async)?.description}}</p>
  <br>
  <h2>Learning Objectives</h2>
  <pre *ngIf="!(course | async)">loading objectives...</pre>
  <ul>
    <li *ngFor = "let objective of (course | async)?.objectives">{{objective.text}}</li>
  </ul>
  <h2>Takeaway</h2>
  <pre *ngIf="!(course | async)">loading takeaways...</pre>
  <ul>
    <li *ngFor = "let takeaway of (course | async)?.takeaways">{{takeaway.text}}</li>
  </ul>
</ion-card-content>

4
投票

假设我们有一个可观察的meals$。我们需要在可观察对象被解析(即获取数据)时显示加载器。 下面是解决方案。

<div *ngIf="meal$ | async as meal; else loading;" >
   //use the meal variable to show some data
</div>
<ng-template #loading>
   //Show your loader here
</ng-template>

0
投票

使用

ngIf="course$|async";else loading
的问题在于,当可观察值解析为像
0 or false
这样的虚假值时,我们会卡在加载程序屏幕上。

为了绕过这个问题,你可以考虑使用更健壮的自定义管道

第一步: 创建一个

loading.pipe.ts
文件

import { Pipe, PipeTransform } from "@angular/core"
import { Observable, isObservable, of } from "rxjs"
import { map, startWith, catchError } from "rxjs/operators"
type LoaderResponse = {
  loading: boolean
  value?: any
  error?: any
}
@Pipe({
  name: "loading",
})
export class LoadingPipe implements PipeTransform {
  transform(val: Observable<any>): Observable<LoaderResponse> {
    return isObservable(val)
      ? val.pipe(
          map((value: any) => ({ loading: false, value })),
          startWith({ loading: true }),
          catchError((error) => of({ loading: false, error }))
        )
      : val
  }
}

第 2 步:在

*.module.ts
文件的声明数组中注册管道

import { LoadingPipe } from "./loading.pipe"

@NgModule({
  declarations: [LoadingPipe,…],
  imports: [...],
  exports: [...],
})
export class SharedComponentsModule {}

第三步:组件文件中的用法

<ng-container *ngIf="course$ | loading | async as course">
 <div *ngIf="course?.value">
  display my resolved values...
 </div>
 <div *ngIf="course?.error">
   Error!
 </div>
 <div *ngIf="course?.loading">
   my loader component...
 </div>
</ng-container>

参考文献和学分 角度文档 异步加载管道

© www.soinside.com 2019 - 2024. All rights reserved.