Evik James Evik James - 4 months ago 26
AngularJS Question

Why does hard coding a YouTube video id work, but using a variable does not?

I am brand new to angular.

I have been trying many things to get embed YouTube videos into my new AngularJS site. I have a json array of video info that I am able to output in a loop.

I want to output the video ids and make create embedded videos. It's not working.

What am I doing wrong here? Why can I not just output the video id in the iframe?

'use strict';

angular.
module('showVideo').
component('showVideo', {
templateUrl: 'show-video/show-video.template.html',
controller: function ShowVideoController() {
this.videos = [

{
name: 'Rush - Kid Gloves - Guitar Solo Cover - 50% speed',
videoid: 'c-8OsVuqoCg'
},

{
name: 'Van Halen - Unchained - Guitar Cover',
videoid: 'Z9n0oIBz8SE'
},

{
name: 'Extreme - More Than Words - Guitar Cover',
videoid: 'gMJcE4kWelE'
}
];
}
});


<div ng-repeat="video in $ctrl.videos">
<span>{{video.name}}</span>
<span>{{video.videoid}}</span>

<!-- this works as expected -->
<iframe type="text/html" width="640" height="360"
ng-src="https://www.youtube.com/embed/Z9n0oIBz8SE" frameborder="0" allowfullscreen></iframe>

<!-- this does not work -->
<iframe type="text/html" width="640" height="360"
ng-src="https://www.youtube.com/embed/{{video.videoid}}" frameborder="0" allowfullscreen></iframe>

</div>


--- update

I expected to see something when I dumped these values. I see nothing though.

<h1>{{$sce.isEnabled()}}</h1>
<h1>{{encodeURI(video.videourl)}}</h1>
<h1>{{$sce.trustAsUrl(video.videourl)}}</h1>
<h1>{{$sce.RESOURCE_URL(video.videourl)}}</h1>

Answer

You should create a filter, like this:

.filter('trustUrl', trustUrl);

trustUrl.$inject = ['$sce'];

function trustUrl($sce) {
  return function(videoId) {
    if (!videoId) return;
    return $sce.trustAsResourceUrl('http://www.youtube.com/embed/' + videoId);
  }
}

Then, in your view:

ng-src="{{ video.videoid | trustUrl }}"

Complete code:

(function() {
  'use strict';

  angular
    .module('showVideo', [])
    .component('showVideo', {
      template: 
        `<div ng-repeat="video in $ctrl.videos">
          <span ng-bind="video.name"></span>
          <span ng-bind="video.videoid"></span>
          <iframe type="text/html" width="640" height="360"
          ng-src="{{ video.videoid | trustUrl }}" frameborder="0" allowfullscreen></iframe>
        </div>`,
      controller: ShowVideoController
    })
    .filter('trustUrl', trustUrl);

  function ShowVideoController() {
    this.videos = [
      {
        name: 'Rush - Kid Gloves - Guitar Solo Cover - 50% speed',
        videoid: 'c-8OsVuqoCg'
      },
      {
        name: 'Van Halen - Unchained - Guitar Cover',
        videoid: 'Z9n0oIBz8SE'
      },
      {
        name: 'Extreme - More Than Words - Guitar Cover',
        videoid: 'gMJcE4kWelE'
      }
    ];
  }

  trustUrl.$inject = ['$sce'];

  function trustUrl($sce) {
    return function(videoId) {
      if (!videoId) return;
      return $sce.trustAsResourceUrl('http://www.youtube.com/embed/' + videoId);
    }
  }
})();
<!DOCTYPE html>
<html ng-app="showVideo">

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
</head>

<body>
  <show-video></show-video>
</body>

</html>