Bailey Dunn
Bailey Dunn

Reputation: 33

Angular properties becoming undefined after initialization/onInit functions

I'm having a weird issue where properties on an angular component I have setup are losing their values after initialization. The component is just a simple html file with a video player on it. (as per below)

<video width="200" controls="true" poster="" id="video">
    <source type="video/mp4" src="http://www.w3schools.com/html/mov_bbb.mp4">
</video>

Then in the components typescript file i've tried creating the property with a predefined value, creating it with no value and then assigning it in the constructor, and then also creating with no value and assigning in the onInit. In all three cases i can see it has the correct value if i console log the value. However in an event called later, the value is undefined. The property has not been bound to any elements or anything like that either.

Create properties with value

export class VideoPlayerComponent implements OnInit {

  timeStarted = 0;
  timePlayed = 0;
  duration = 0;
  video: HTMLVideoElement;

  constructor() {
    
  }


  ngOnInit(): void {
    //Have values when logged here
    console.log("Time Started: " + this.timeStarted);
    console.log("Time Played: " + this.timePlayed);
    console.log("Duration: " + this.duration);
    this.video = <HTMLVideoElement> document.getElementById("video");

    this.video.addEventListener("pause", this.videoStoppedPlaying);
    

  }
  
  videoStoppedPlaying(event) {
    //is undefined here
    console.log("Time Started: " + this.timeStarted);
    console.log("Time Played: " + this.timePlayed);
    console.log("Duration: " + this.duration);
  }
}

Create properties then assign in constructor

export class VideoPlayerComponent implements OnInit {

  timeStarted: number;
  timePlayed: number;
  duration: number;
  video: HTMLVideoElement;

  constructor() {
    this.timeStarted = 0;
    this.timePlayed = 0;
    this.duration = 0
    this.video = <HTMLVideoElement> document.getElementById("video");
  }


  ngOnInit(): void {
    //Have values when logged here
    console.log("Time Started: " + this.timeStarted);
    console.log("Time Played: " + this.timePlayed);
    console.log("Duration: " + this.duration);

    this.video.addEventListener("pause", this.videoStoppedPlaying);
    

  }

  videoStoppedPlaying(event) {
    //is undefined here
    console.log("Time Started: " + this.timeStarted);
    console.log("Time Played: " + this.timePlayed);
    console.log("Duration: " + this.duration);
  }

}

Create properties then assign in onInit

export class VideoPlayerComponent implements OnInit {

  timeStarted: number;
  timePlayed: number;
  duration: number;
  video: HTMLVideoElement;

  constructor() {
    
  }


  ngOnInit(): void {
    this.timeStarted = 0;
    this.timePlayed = 0;
    this.duration = 0
    this.video = <HTMLVideoElement> document.getElementById("video");
    //Have values when logged here
    console.log("Time Started: " + this.timeStarted);
    console.log("Time Played: " + this.timePlayed);
    console.log("Duration: " + this.duration);

    this.video.addEventListener("pause", this.videoStoppedPlaying);
    

  }

  videoStoppedPlaying(event) {
    //is undefined here
    console.log("Time Started: " + this.timeStarted);
    console.log("Time Played: " + this.timePlayed);
    console.log("Duration: " + this.duration);
  }

}

Could anyone please provide any insight on what might be causing the value to disappear after initialization and loading?

Upvotes: 2

Views: 1973

Answers (3)

Trirandom
Trirandom

Reputation: 87

You shouldn't be using addEventListener("pause", this.videoStoppedPlaying); But use the (pause) event in the HTML template instead.

Like this:

<video width="200" controls="true" poster="" id="video" (pause)="videoStoppedPlaying($event)">
    <source type="video/mp4" src="http://www.w3schools.com/html/mov_bbb.mp4">
</video>

Your mistake here is that you didn't bind this. You can probably do: this.video.addEventListener("pause", this.videoStoppedPlaying.bind(this));

Also, please consider using @ViewChild() instead of document.getElementById("video").

Upvotes: 1

Ron Gabbay
Ron Gabbay

Reputation: 97

you can use the video "event" to get all the data you need and assign it to the properties you created

your VideostoppedPlaying Function can look like this

    videoStoppedPlaying(event) {
    this.duration = event.target.duration
    this.timePlayed = event.target.currentTime
    console.log("Time Played: " + this.timePlayed);
    console.log("Duration: " + this.duration);
  }
}

And dont forget to add "event" when youre calling the function at the addEventListener

    this.video.addEventListener("pause",e=> this.videoStoppedPlaying(e));

Upvotes: 1

Elmehdi
Elmehdi

Reputation: 1430

This is because the key word this does not refer to your component VideoPlayerComponent as you might think, in your case it is gonna be referring to this.video.
Because of the following line of code:

this.video.addEventListener("pause", this.videoStoppedPlaying);

The function videoStoppedPlaying is invoked inside the object video and as you way or may not know the keyword this refers to the object where he actually is called in, thus reffering to video.
Inside video object there is no timeStarted and no timePlayed propery and that is why they are undefined, but there is a property called duration and that is why you get a value for duration.
If you want to know more about the properties that exists inside video object check this documentation and go HTML Audio/Video Properties.
I also created a live demo for you with one more property.

Upvotes: 1

Related Questions