2

i have a simple angular application to play audio using JavaScript web Audio Object below is

app.component.ts

export class AppComponent {
  title = 'media player';
  audio;
  currentTime: number;

  constructor() {
    this.audio = new Audio();
    this.audio.src = './Music/demo2.MP3';
    this.audio.play();
    this.currentTime = this.audio.currentTime;
  }
}

and app.component.ts

<h4>{{ currentTime }}</h4>

everything works fine but the view isn't update as the model changes

jonrsharpe
  • 107,083
  • 22
  • 201
  • 376
Ochui Princewill
  • 140
  • 1
  • 15

2 Answers2

2

Angular does update binding on browser events for the same Angular uses zonejs which monkey patches several browser events, and it fires detectChanges method to keep binding in a sync.

In this case Angular doesn't update binding, since Audio API event's doesn't monkey patch by zonejs. For such scenarios you have to run change detection manually to update bindings manually. You could use ontimeupdate event handler of audio API.

import { ChangeDetectorRef, Component } from '@angular/core';

export class AppComponent {
  title = 'media player';
  audio;
  currentTime: number;

  constructor(private cd: ChangeDetectorRef ) {
  }
  ngOnInit(){
     this.audio = new Audio();
     this.audio.src = './Music/demo2.MP3';
     this.audio.play();
     //this will make sure to update when time updates.
     this.audio.ontimeupdate = (event) => {
        this.currentTime = this.audio.currentTime;
        this.cd.detectChanges();
     }
  }
}
Pankaj Parkar
  • 130,886
  • 22
  • 223
  • 289
-2

Here is the setInterval approach

export class AppComponent {
  title: string = 'media player';
  audio: Audio;
  currentTime: number;

  constructor() {
    this.audio = new Audio();
    this.audio.src = './Music/demo2.MP3';
    this.audio.play();
    this.currentTime = this.audio.currentTime;
  }
  
   ngOnInit() {
     setInterval(() => {
      this.currentTime = this.audio.currentTime;
    }, 1000);
   }
}

But as the @user184994 mentioned, simply just by using the audio.currentTime on the frontend might be far simpler and effective approach.

<h4>{{ audio.currentTime }}</h4>
Praveen Premaratne
  • 2,462
  • 1
  • 14
  • 23
  • I consider `setInterval` a code smell. It complicates the code and tests, and doesn't seem necessary given when the OP is trying to accomplish. – stealththeninja Oct 21 '17 at 18:47
  • @stealththeninja OP's problem is that `currentTime` not updating constantly when the audio is playing, this is an approach that I would consider. That's why I mentioned of using the `audio.currentTime` itself, as I'm assuming, will get updated as the audio is playing, is far stable and effective. – Praveen Premaratne Oct 21 '17 at 18:58
  • It's preferable to use event listeners over `setInterval`, and media elements have a `timeupdate` event: https://developer.mozilla.org/en-US/docs/Web/Events/timeupdate – stealththeninja Oct 21 '17 at 19:04
  • @stealththeninja yes, I used the same in my answer :) – Pankaj Parkar Oct 24 '17 at 16:07