26

I need to pass async variable to the function. Something like this:

<div class="team" (click)="addToFavorite((match | async)?.id)">

And of course I have an error.

Parser Error: Cannot have a pipe in an action expression.

Maybe there is a way to transform async variable in JavaScript?

Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
AlexZvl
  • 2,092
  • 4
  • 18
  • 32

5 Answers5

39

Here is how I solved it :

<div *ngIf="(match | async) as match" class="team" (click)="addToFavorite(match.id)">

It's short, simple and it works.

<ng-container *ngIf="(match | async) as match">
   <div class="team" (click)="addToFavorite(match.id)">
   </div>
</ng-container>

Update January 20th 2021

To be more clear I would name match observable source as match$.

And we can now use the new @ngrx/component package and use the new ngrxLet structural directive :

<ng-container *ngrxLet="match$ as match">
  <div class="team" (click)="addToFavorite(match.id)">
  </div>
</ng-container>

The async pipe is no more necessary. More info on ngrx.io, on this link.

Benoît Plâtre
  • 596
  • 1
  • 5
  • 4
16

Another option for simple variables and without any observables is writing value of the variable into hidden input:

<div *ngIf="(match | async)?.id">
    <input  #myControl [value]="(match | async).id" type="hidden" />
    <div class="team" (click)="addToFavorite(myControl.value)">
</div>
Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Ilya Loskutov
  • 1,967
  • 2
  • 20
  • 34
1

Seems you need to use a helper method:

<div class="team" (click)="onClick(match)">
class MyComponent {
  onClick(event) {
    event.then(val => this.addToFavorite(val?.id);
  }
  addToFavorite(val) {
  }
}
Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I cannot use this `val?.id` so I just pass value and I still get observable in the addToFavorite() not a value itself – AlexZvl Oct 28 '16 at 07:53
  • 1
    Why can't you use `val?.id`? – Günter Zöchbauer Oct 28 '16 at 07:54
  • As far as I can tell, the `?` operator is only available inside angular 2 templates, and not inside Typescript component code. This feature hasn't been implemented yet for Typescript, but It seems to be in the works: https://github.com/Microsoft/TypeScript/issues/16 – Devon Sams Apr 20 '17 at 17:02
  • @DevonSams thanks. I'm so used to it from Dart, I missed that it's not yet in TS. You are right, currently it is only available in template bindings. – Günter Zöchbauer Apr 20 '17 at 17:03
1

What about:

<div class="team" (click)="addToFavorite(match)">

and then in your code:

addToFavorite(obs: Observable<any>) {
  obs.take(1).subscribe(value => {
    addToFavoriteById(value.id);
  });
}
Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Meir
  • 14,081
  • 4
  • 39
  • 47
1

You can't do it in template.

But you can:

<div class="team" (click)="addToFavorite()">

and in your .component.ts:

public addToFavorite() {
  this
    .match  // should retain last value (e.g. use BehaviorSubject)
    .first() // completes after passing one value only
    .subscribe(
      (matchValue) => {
        // your logic here
    });
}

Note: We are subscribing (and immediately unsubscribing), similarly async pipe subscribes to Observable.

Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
m4js7er
  • 119
  • 1
  • 3