0

In order to load a youtube movie in an iframe, I have the following in my template:

<iframe [src]="getYouTubeUrl(currentItem.id)" frameborder="0" allowfullscreen></iframe>

In the component I have defined:

getYouTubeUrl(id:string):SafeResourceUrl {
   let url:string = `https://www.youtube.com/embed/${id}`;
   return this.sanitizer.bypassSecurityTrustResourceUrl(url);
}

Somehow, this function is called infinitely (while the resulting url doesn't change). The result is that the video cannot be loaded. What could be wrong here?

dndr
  • 2,319
  • 5
  • 18
  • 28
  • Use pure pipe instead. See also http://stackoverflow.com/questions/38037760/how-to-set-iframe-src-in-angular-2-without-causing-unsafe-value-exception/38037914#38037914 and issue on github https://github.com/angular/angular/issues/11518 – yurzui Oct 03 '16 at 14:15
  • Thanks, this works! :) I don't know why change detection is ran multiple times without the pipe but only once with the pipe though? Could it be because now the function returns a string (the url), which is a primitive, and not a SafeResourceUrl, which is not a primitive? – dndr Oct 03 '16 at 14:45
  • Pure pipe will be executed only when it detects a pure change to the input value. On the other hand your function within template will invoke every `Application.tick` http://stackoverflow.com/questions/39757603/unraveling-angular-2-book-chapter-1-example-5/39761822#39761822 – yurzui Oct 03 '16 at 14:52

1 Answers1

1

Angulars change detection calls the method every time when change detection is run, which is usually quite often. This is the reason binding to functions or methods is discouraged.

Instead assign the result of the function or method to a property and bind to this property from the view instead.

<iframe [src]="youTubeUrl" frameborder="0" allowfullscreen></iframe>
ngOnInit() {
  this.youTubeUrl = getYouTubeUrl(this.currentItem.id);
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • What if I use a repeater (ngFor) on a list of images with a function for the [src]? – alex351 Dec 14 '17 at 10:45
  • 1
    The same. Don't bind functions. Prepare a new array that contains the result for each item (or add the data to the "list of images") and then bind to that array. – Günter Zöchbauer Dec 14 '17 at 11:01