Friso Hoekstra
Friso Hoekstra

Reputation: 885

Angular async pipe not working with fromEvent

Stackblitz: https://stackblitz.com/edit/angular-w7vlnu

I am creating an Observable from an HTMLAudioElement using fromEvent:

playTime(): Observable<any> {
    return fromEvent(myMediaElement, 'play').pipe(
        map(e => e.type + Date.now())
    );
}

playTime() gets passed to a child component via an @Input()

In the component, when I subscribe:

// component.ts

@Input() currentTime: Observable<any>;

playDate = '';

ngOnInit {
    this.currentTime.subscribe(v => this.playDate = v);
}
// component.html

// will render
{{ playDate }}  

// will not render
{{ currentTime | async }}

I tried ye olde ChangeDetectorRef.detectChanges() and Application.tick() to no avail.

Something I need to know about fromEvent and the way the subscription works? Other Observables constructed from BehaviorSubject work fine in this component

Upvotes: 1

Views: 721

Answers (1)

Dino
Dino

Reputation: 8292

I checked your Stackblitz. It's not a good practice that you are passing a service function as an @Input() by directly referencing the service from the template.

Therefore, instead of referencing the service in a template like your currently do:

<audio-container [currentTime]="audio.currentTime()">

You should create a new Observable which will reference to the one from a service, and then use it in a template.

<audio-container [currentTime]="$currentTime">

app.component.ts

$currTime: Observable<any>;

constructor(public audio: AudioPlayerService) {
  this.$currentTime = this.audio.currentTime();
}

Stackblitz

ADVICE: Don't reference the service variables / functions directly from a template.

BAD:

<button (click)="audio.play(version1)">Play Song 1</button>

GOOD:

<button (click)="play(version1)">Play Song 1</button>

play(version) {
   this.audio.play(version).subscribe(...);
}

Upvotes: 3

Related Questions