Angular异步管道与对象属性

88

我需要在没有ngFor的情况下使用异步管道(async pipe)。我需要检查一个通过observable异步加载的对象的属性。

这是我想要的,但它不起作用:

 <ion-item *ngIf="user$.anonymouse | async">
     <ion-label>Login</ion-label>
 </ion-item>

//编辑:我在使用上述代码时遇到了这个错误

异常:在[!User$.anonymouse | async in SettingsPage@27:22]中,管道'AsyncPipe'的参数“true”无效

有什么办法可以解决这个问题吗?

我知道可以在Ctrl中订阅此observable并将值存储到正常变量中,但我不想这样做,因为会影响性能等原因。


那么,问题出在哪里? - Günter Zöchbauer
https://angular.io/docs/ts/latest/api/common/AsyncPipe-class.html AsyncPipe不需要ngFor。 - David L
如果我使用上面的代码,我会遇到错误,我已经将错误添加到问题中。 - Daniel Suchý
@DavidL 目前(2.0+)它可以工作。 :) - sandrooco
4个回答

75

错误异常信息非常准确,因为*ngIf指令期望truefalse,并使用结果表达式来确定是否在DOM中呈现HTML元素。

异常:在[!user$.anonymouse | async in SettingsPage@27:22]中针对管道“AsyncPipe”的无效参数'true'

你的表达式是user$.anonymouse,它被评估为真值,但不幸的是,你不能在这个指令中使用async管道。例如,async管道可以"转换"(也称为"管道")输入,并将输出暴露在*ngFor指令的范围内。

该管道接受以下三种可能类型之一(关于AsyncPipe的详细信息请参见此处):

transform(obj: Observable<any>| Promise<any>| EventEmitter<any>)

有没有解决方法?

是的,你可以按照设计意图使用它。例如,在一个*ngFor指令中:

<ion-item *ngFor="(user$ | async)?.anonymouse">
     <ion-label>Login</ion-label>
</ion-item>

或者你可以完全删除管道符号,因为 *ngIf 指令并不需要它:

<ion-item *ngIf="user$.anonymouse">
     <ion-label>Login</ion-label>
</ion-item>

72
需要澄清上述讨论中使用AsyncPipe和NgFor的用法。表达式*ngFor="user$.anonymouse | async"会将user$anonymouse属性传递给AsyncPipe,但我认为这会导致undefined,因为user$是一个observable,而不是observable的输出。为了在user$上运行AsyncPipe,然后访问结果中的anonymouse属性,您需要使用*ngFor="(user$ | async)?.anonymouse" - Sean
4
我认为@Sean的评论应该成为答案并标记为被接受的答案。被接受的答案提供了一个很好的解释;然而,正如Sean指出的那样,(user$ | async)?.anonymouse是OP需要做的(也是对我有效的!谢谢!) - Kabb5

71

如@Sean在评论中所述,您的*ngIf语句应该基于返回的user$对象的属性anonymouse。因此:

<ion-item *ngIf="(user$ | async)?.anonymouse">
     <ion-label>Login</ion-label>
</ion-item>

这对我很有效,以下是如何使用下面管道结果的示例:

组件

 message$: Observable<{message: string}>;

  private messages = [
    {message: 'You are my hero!'},
    {message: 'You are the best hero!'},
    {message: 'Will you be my hero?'}
  ];

  constructor() { this.resend(); }

  resend() {
    this.message$ = Observable.interval(500)
      .map(i => this.messages[i])
      .take(this.messages.length);
  }

查看

<h2>Async Hero Message and AsyncPipe</h2>
<p>Message: {{ (message$ | async)?.message }}</p>
<button (click)="resend()">Resend</button>`

这里可以找到一个可工作的示例


44
<!-- This is needed to wait for async pipe to resolve -->
<div *ngIf="user$ | async as user"> 

   <!-- Only on resolve of async pipe -->
   <ion-item *ngIf="user.whateverPropertyYouWantToCheck">
        <ion-label>Login</ion-label>
    </ion-item>
</div>
请注意,我从user$切换到了user,如果您愿意可以使用相同的变量名,但这使得该值不再是异步管道更加清晰。

6
在我看来,这是最好的答案。 - JoshMB
1
是的,这比 *ngIf="(user$ | async)?.anonymouse" 更好。 - Ifch0o1

0

isAnonymouse$ = user$.pipe(map(user => user?.anonymouse));

是匿名用户吗?= user$.pipe(map(user => user?.anonymouse));

<ion-item *ngIf="user$.anonymouse | async">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接