繁体   English   中英

Angular 显示模板,如果 observable 是错误的异步 pipe

[英]Angular display template if observable is falsey with async pipe

我有一个 API 调用,它可能会返回一些数据,或者如果不存在数据,可能会返回一些虚假的东西。 如果有数据,我想从 stream 中tap出来并做一些副作用,但如果是假的,我希望没有副作用发生但仍然显示我的模板代码。

我正在使用异步 pipe 来获取模板中的数据,但如果数据是假的,它将不会显示。

我已经看到用 object 包装ngIf的技术,因此它的评估结果为真,但它似乎不是我的代码的正确解决方案。

我的模板:

<form *ngIf="loadedData$ | async">
  ...
</form>

我的 class:

loadedData$: Observable<boolean>;

ngOnInit(): void {
  this.loadedData$ = this.getCurrentBranding().pipe(
    tap(branding => {
      if (branding) {
        // Do side effects
      }
    }),
    // current hack to make the template show
    map(() => true)
  );
}

private getCurrentBranding(): Observable<Branding> {
  // API call, may return an object, or null
}

您始终可以尝试使其尽可能语义化。 您使用map的方法不是一个坏主意,只是您实际上失去了对数据的访问权限。 最好将它分成两个Observables

readonly data$: Observable<BrandingData> = this.getCurrentBranding().pipe(
  shareReplay({ refCount: true, bufferSize: 1 })
);

readonly loadingData$: Observable<boolean> = this.data$.pipe(
  mapTo(false),
  startWith(true)
);

然后,您可以通过检查是否正在加载数据来显示您的表单:

<form *ngIf="(loadingData$ | async) === false"></form>

这里发生的是,通过订阅模板中的loadingData$ ,实际上也订阅了data$ osbervable,这将触发 API 请求。 通过使用shareReplay ,您可以确保此请求仅在每次订阅时执行一次。

“典型”是使用 object 作为“如果”方式

<!--see that the if is always "true" -is an object- -->
<form *ngIf="{response:loadedData$ | async} as res">
   <!--you has the response in res.response-->
   <ng-container *ngIf="res.response===false">
      the result of the call is false
   </ng-container>
   <ng-container *ngIf="res.response!===false">
    {{res.response|json}}
   </ng-container>
</form>

我一直习惯于为我的组件使用一个可观察的对象来合并多个流,并将它们组合成一个 state。 通常这涉及到扫描操作符,但在这种情况下它不是必需的(尽管也许你也想合并这些副作用)。

在下面的代码中, getCurrentBranding将在组件中的异步pipe 订阅时执行。 为了防止多次执行,您可以使用一个根元素,使用 Angular表达式将发射转换为模板变量。 或者,您可以使用shareReplay

startWith运算符用于提供初始值,因此将始终显示根元素。 该表单最初将被隐藏,直到从 api 返回结果。 数据将来自相同的可观察对象,并从根元素处创建的模板变量访问。

this.state$ = this.getCurrentBranding().pipe(
  tap(branding => { /* Do side effects */ ),
  map(data => ({ data, isLoaded: true}),
  startWith(({ data: [], isLoaded: false})
);
<ng-container *ngIf="(state$ | async) as state">
  <form *ngIf="state.isLoaded">
    <!-- ... -->
  </form>
  <ol *ngFor="let o of state.data">
    <!-- ... -->
  </ol>
</ng-container>

与 eliseo 答案类似,我将boolean boolean可选(Java 风格)中:

featureFlag$: Observable<Optional<boolean>>;

然后在模板中:

<div *ngIf="featureFlag$ | async as featureFlag">
  <div ngIf="featureFlag.get()">
</div>

就我而言,我的主要出版商是 boolean promise。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM