1

The view can't update the value of status variable.

This is an extract of my code deleted the code not relevant:

component.ts

export class MyComponent implements OnInit {
   private status: string;

   ngOnInit() {
      this.status = "abc"; // OK binding

      window['onYouTubeIframeAPIReady'] = (e) => {
            this.player = new window['YT'].Player('player', {
              videoId: this.video.videoId,
              events: {
                'onStateChange': this.onPlayerStateChange.bind(this)     
              }
            });
        };
    }

    onPlayerStateChange(event) {
       switch (event.data) {
          case window['YT'].PlayerState.PLAYING:
              this.status= "xyz"; //Not possible binding
              break;
}

component.html

<span>{{status}}</span> // it shows only abc, the expected is xyz

Anybody has an idea how can I update the variable in the window and it reflects on the view?

Antoine V
  • 6,998
  • 2
  • 11
  • 34
  • did you tried life-cycle hooks – Amir Fawzy Nov 12 '18 at 14:54
  • Can you make a stackblitz with the video example? The `window.onload` example doesn't work because the event is not triggered (see [this stackblitz](https://stackblitz.com/edit/angular-cdvpuo)). The window is probably already loaded when the event handler is set. – ConnorsFan Nov 12 '18 at 15:15
  • The `window.onload` still doesn't work, even with `setTimeout`, because the event handler is not executed. You can test it with a `console.log`. – ConnorsFan Nov 12 '18 at 15:28
  • So, back to my original question: can you provide a stackblitz for the video case? – ConnorsFan Nov 12 '18 at 15:32

2 Answers2

1

I'm Completely changing my previous answer because that doesn't seem to be problem in your case

I'm not sure why the property is not updating on the template but the value gets changed in the ts- may be the window function issue i think

After some research i have manual triggered the changes on the onPlayerStateChange(event)

Inject ChangeDetectorRef in your constructor

constructor(private dect: ChangeDetectorRef){}

Add this.dect.detectChanges(); after you property change - check out the code below

onPlayerStateChange(event) {
    switch (event.data) {
      case window['YT'].PlayerState.PLAYING:
          this.name = "yyy";
          this.dect.detectChanges(); //this will manually trigger the changes on your properties
          console.log("I'm playing");
        break;     
    }; 
  }

Hope it might work, solution might not be a traditaionl way but you can use this as a workaround - happy coding :)

Rahul
  • 2,040
  • 2
  • 11
  • 29
0

Change: private status: string;

to public status: string;

Declared variables need to be public for the template to be able to access them. Good explanation here: Should private variables be accessible in the template?

Rutger van Dijk
  • 330
  • 1
  • 9
  • Moreover, testing the variable change `this.name = 'yyy';`, is better done by a click on a button or on a `setTimeout(() => { this.name = 'yyy'; },0);` – Rutger van Dijk Nov 12 '18 at 14:49
  • It should fix it, make sure you are testing the changing of the `status` variable OK. Try using a `setTimeout` instead of within your `onPlayerStateChange(event)` function. If that doesn't work, I recommend setting up a Plunkr, so we can evaluate the full code :) – Rutger van Dijk Nov 12 '18 at 14:59
  • Ha, indeed. The setTimeout does actually change the variable in the template: https://stackblitz.com/edit/angular-ktxzzn - So your problem seems to be a scoping issue with the YouTube event.. – Rutger van Dijk Nov 13 '18 at 08:13
  • Injecting the ChangeDetectorRef like Rahul also implies below will solve it: https://stackblitz.com/edit/angular-ktxzzn – Rutger van Dijk Nov 13 '18 at 08:17