admin管理员组

文章数量:1388126

My Project runs on Angular 8 with typescript.

Im trying to get an html audio element by id and store it in a variable. Then i want to get the duration out of the Element and store it in another variable.

As seen in a working example, in Javascript, this would go as:

HTML

<audio id="music" preload="true">
  <source src="./assets/img/hollywood.mp3">

JS

var music = document.getElementById('music'); 
var duration = music.duration;

now my translation to typescript is this:

TS

public music = <HTMLAudioElement>document.getElementById("music");
public duration = this.music.duration;

But when i load the page, i get the error "Uncaught (in promise): TypeError: this.music is null" and i dont get why.

My Project runs on Angular 8 with typescript.

Im trying to get an html audio element by id and store it in a variable. Then i want to get the duration out of the Element and store it in another variable.

As seen in a working example, in Javascript, this would go as:

HTML

<audio id="music" preload="true">
  <source src="./assets/img/hollywood.mp3">

JS

var music = document.getElementById('music'); 
var duration = music.duration;

now my translation to typescript is this:

TS

public music = <HTMLAudioElement>document.getElementById("music");
public duration = this.music.duration;

But when i load the page, i get the error "Uncaught (in promise): TypeError: this.music is null" and i dont get why.

Share Improve this question asked Apr 29, 2020 at 12:04 DuB loxxDuB loxx 2352 gold badges6 silver badges14 bronze badges 5
  • And if you remove this from this.music.duration ? I am not familiar with TS. – Fasani Commented Apr 29, 2020 at 12:08
  • 1 It's not a typescript error. preload=true tells the browser to fetch the audio first. But it's not done loading by the time you execute the script – MonteCristo Commented Apr 29, 2020 at 12:09
  • 1 @Fasani, if i remove this, the variable music is not recognized – DuB loxx Commented Apr 29, 2020 at 12:11
  • @MonteCristo if i remove that, the same error is printed – DuB loxx Commented Apr 29, 2020 at 12:12
  • Access DOM-elements in ngAfterViewInit() instead – Salmin Skenderovic Commented Apr 29, 2020 at 12:12
Add a ment  | 

2 Answers 2

Reset to default 1

You could use ViewChild and ElementRef using a template reference variable to keep things the Angular way. Try the following

Template

<audio #stream autoplay (play)="onPlay()">
  <source src="https://upload.wikimedia/wikipedia/mons/c/c8/Example.ogg">
</audio>

Controller

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

@Component({
  selector: 'my-app'
})
export class AppComponent {

  audioPlayer: HTMLAudioElement;

  @ViewChild('stream') set playerRef(ref: ElementRef<HTMLAudioElement>) {
    this.audioPlayer = ref.nativeElement;
  }

  onPlay() {
    console.log(this.audioPlayer.duration);
  }
}

It binds the nativeElement of the element reference to the audioPlayer variable using set.

ngAfterViewInit() cannot guarantee accessing the duration would return the correct value since the audio may not have started playing. In that case, it would return null. So I bound it to the play event to get the duration.

Working example: Stackblitz

Add #nameForYourRef

<audio #myAudio preload="true">
  <source src="./assets/img/hollywood.mp3">
</audio>

Then access your element on viewInit

@ViewChild('myAudio') myAudioRef: ElementRef;

  ngAfterViewInit() {
    // Console log some methods to see that it is working
    console.log(
      this.myAudioRef.nativeElement.play,
      this.myAudioRef.nativeElement.pause,
    )
  }

Demo: https://stackblitz./edit/angular-a8jahz

本文标签: javascriptHow to translate quotget element by idquot into typescriptStack Overflow