htmlangularjshtml-object

Embedding with 'object' tag not working on dynamic data


I am trying to embed youtube videoes using the object tag instead of iframes. However, it doesn't work even though element.url points to the correct url. If I replace {{element.url}} (in object tag) with just the url, it works just fine. The iframe works as it is.

<div ng-show="element.url" id="resourceFrame">      
  <iframe class="iframe" width="500" height="325"  src="{{element.url}}" frameborder="0" allowfullscreen></iframe>
  <object width="500" height="325" >
    <param
      name="{{element.name}}"
      value="{{element.url}}">
    </param>
    <param
      name="allowscriptaccess"
      value="always">
    </param>
    <param
      name="allowFullScreen"
      value="true">
    </param>
    <embed
      src="{{element.url}}"
      type="application/x-shockwave-flash"
      allowscriptaccess="always"
      allowfullscreen="true"
      width="500"
      height="325">
    </embed>
  </object> 
  <div id="text-content" ng-show="element.text">
    <p>{{element.text}}</p>
  </div>
</div>

Why does {{element.url}} work in iframe, but not object tag?


Solution

  • The problem has been described in many SO questions and answers. In short, as far as I understood correctly, it's because you "execute" remote <object>. In this case all <object> see as source, is really just literal {{ element.url }}.

    You can go around this by creating your own Youtube directive. For example:

    app.directive('youtube', function() {
        return {
            restrict: 'E',
            scope: {
              movie: '@'
            },
            link: function(scope, element) {
                var object = '<object width="560" height="315">' +
                  '<param name="movie" value="' + scope.movie + '" />' +
                  '<embed ' +
                  '  src="' + scope.movie + '" ' +
                  '  type="application/x-shockwave-flash" ' +
                  '  width="560" ' +
                  '  height="315" />' +
                '</object>';
                element.replaceWith(object);
            }
        };
    });
    

    Usage in HTML template would be as simple as

    <body ng-controller="MyCtrl">
        <youtube movie="{{ movie.url }}"></youtube>
    </body>
    

    And in controller, you have your movie

    $scope.movie = { 
        name: 'movie',
        url: '//www.youtube.com/v/YrrzgE8J1KI'
    };  
    

    Example Plunker here http://plnkr.co/edit/RJyewh which you can continue to improve by adding new attributes (width and so on) as you see appropriate.

    Of course you could wrap any other <object> in directive, too.