Search code examples
angulartypescriptyoutubeangular-pipe

Error attempting SafePipe to Sanitize Embed Youtube Videos


I have a bit of a dilemma while attempting to embed YouTube videos in my Angular application.

I have tried using Angular's DomSanitizer method "bypassSecurityTrustResourceUrl()", and it did properly display the videos. But the DOM kept updating causing refreshes which would obviously stop the currently playing video. Please see that code:

media.component.ts

import { Component, OnInit, Injectable } from '@angular/core';
import { AngularFire } from 'angularfire2';
import { DomSanitizer } from '@angular/platform-browser';

import { VideoService } from '../../../services/videos/video.service';

@Component({
  selector: 'app-media',
  templateUrl: './media.component.html',
  styleUrls: ['./media.component.css']
})

@Injectable()
export class MediaComponent implements OnInit {

  videos = [];

  constructor( public af: AngularFire,
               private videoService: VideoService,
               private sanitizer: DomSanitizer ) {}


  getVideos() {
    this.videoService.getVideos().subscribe((data) => {
      this.videos = data;
    });
  }

  sanitizeVideo(index: number) {
    return this.sanitizer.bypassSecurityTrustResourceUrl(this.videos[index].videoUrl);
 }

  ngOnInit() {
    this.getVideos();
  }

media.component.html

<div class="container" *ngIf="videos">
  <h1 class="my-4">Videos
    <small>More to come</small>
  </h1>
<br><br>
  <div *ngFor="let video of videos; let i = index">
    <div class="row">
      <div class="col-md-6">
        <a href="#">
          <iframe width="560" height="315" [src]= "sanitizeVideo(i)" frameborder="5" allowfullscreen></iframe>
        </a>
      </div>
      <div class="col-md-5">
        <h3>{{ video.videoTitle }}</h3>
        <p>{{ video.videoDescription }}</p>
      </div>
    </div>
    <hr>
  </div>
</div>




So I found more information on using a pipe to avoid the refresh issue. However that creates the below error:

error_handler.js:60 Error: Uncaught (in promise): Error: Cannot match any 
routes. URL Segment: 'null'
Error: Cannot match any routes. URL Segment: 'null'

safe.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser';

@Pipe({
  name: 'safe'
})
export class SafePipe implements PipeTransform {

  constructor( private sanitizer: DomSanitizer ) {}

  transform(url) {
    return this.sanitizer.bypassSecurityTrustResourceUrl(url);
  }

}

media.component.html

<div class="container" *ngIf="videos">
  <h1 class="my-4">Videos
    <small>More to come</small>
  </h1>
<br><br>
  <div *ngFor="let video of videos">
    <div class="row">
      <div class="col-md-6">
        <a href="#">
          <iframe width="560" height="315" [src]= "video.videoUrl | safe" frameborder="5" allowfullscreen></iframe>
        </a>
      </div>
      <div class="col-md-5">
        <h3>{{ video.videoTitle }}</h3>
        <p>{{ video.videoDescription }}</p>
      </div>
    </div>
    <hr>
  </div>
</div>

Any advice on properly displaying embed YouTube videos without causing constant DOM refresh?


Solution

  • Don't call sanitizeVideo() from a view binding. This way it will be called every time change detection runs. Calk it from code and assign the result to a field and bind to that field instead,