URL sanitization is causing refresh of the embedded YouTube video

JavascriptAngularYoutube

Javascript Problem Overview


I have a problem with my AngularJS 2 app (I am using RC5 version of AngularJS 2). It seems that a sanitized URL is triggering change detection which then updates the div below despite not having any changes in my component state.

From user point of view this manifests itself as reload of the video while it is playing.

So in my component view I have:

<div *ngIf="isVideo(item)">
   <iframe [src]="getTrustedYouTubeUrl(item)" scrolling="no" frameborder="0" allowfullscreen></iframe>          
</div>

The implementation of the function above in the component code is:

getTrustedYouTubeUrl(linkedVideo:LinkedVideoModel) {
    return this.sanitizer.bypassSecurityTrustResourceUrl(linkedVideo.video.url);
}    

In debugger I see that the div gets refreshed quite often, by something triggered in AngularJS 2 framework.

The issue goes away, if I replace the HTML snippet above with a hard-coded URL:

<div *ngIf="isVideo(item)">
   <iframe src="<hardcoded youtube url here>" scrolling="no" frameborder="0" allowfullscreen></iframe>          
</div> 

So I am suspecting that URL sanitization is causing it.

Can anyone point me in the right direction? A working example of embedded YouTube videos that have their URL bound to a property on the component maybe?

Javascript Solutions


Solution 1 - Javascript

Figured it out.

For anyone interested. The problem was the use of this function in my html

   [src]="getTrustedYouTubeUrl(item)"

The reload side effect was gone once I changed the code to calculate the safe url when the data is loaded in my service and changed the iframe binding to this

    <iframe [src]="item.video.safeUrl" scrolling="no" frameborder="0" allowfullscreen></iframe>    

Note thatr I am now binding to a property.

Solution 2 - Javascript

I would try to use it with pure pipe

> Angular executes a pure pipe only when it detects a pure change to the > input value. A pure change is either a change to a primitive input > value (String, Number, Boolean, Symbol) or a changed object reference > (Date, Array, Function, Object).

Pipe might look like (RC.6 - DomSanitizer becomes instead of DomSanitizationService):

@Pipe({ name: 'safe' })
export class SafePipe implements PipeTransform {
  constructor(private sanitizer: DomSanitizer) {}
  transform(url) {
    return this.sanitizer.bypassSecurityTrustResourceUrl(url);
  }
}

And use it as the following:

<iframe [src]="url | safe" frameborder="0" allowfullscreen></iframe> 

Plunker Example (try to push button)

Solution 3 - Javascript

Combined the previous answers to get it working this way:

component.ts (only the relevant parts)

import { DomSanitizer } from '@angular/platform-browser';

constructor( 
  private sanitizer: DomSanitizer   
) {
  this.sanitizer = sanitizer;
}

ngOnInit() {
 this.getTrustedUrl('http://someUrl');
}

getTrustedUrl(url:any){ 
 this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(url);
}

template.html

<iframe      
  [src]='this.safeUrl'>
</iframe>

Solution 4 - Javascript

You can keep your original solution and just use changeDetection: ChangeDetectionStrategy.OnPush

>


Solution 5 - Javascript

<iframe #ytplayer  width="100%" height="235" frameborder="0" src="">
</iframe>    

@ViewChild('ytplayer', null) ytPlayer: ElementRef;

ngOnInit() {
  this.ytPlayer.nativeElement.src = this.act.iframe;
}

Reloading happens because of using sanitizer.bypassSecurityTrustResourceUrl. So we should not use it. I think it is more comfortable. Thanks.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionaylsView Question on Stackoverflow
Solution 1 - JavascriptaylsView Answer on Stackoverflow
Solution 2 - JavascriptyurzuiView Answer on Stackoverflow
Solution 3 - JavascriptAnthonyView Answer on Stackoverflow
Solution 4 - JavascriptMurhaf SousliView Answer on Stackoverflow
Solution 5 - JavascriptDaniel RocciView Answer on Stackoverflow