Building an AngularJS Directive for Cat Videos

Written by David on April 6, 2013

Let's build an AngularJS directive that shows Youtube videos. It's not too involved, but enough that it'll require a little bit of digging.

Let's get the HTML embed for a funny cat video.

<iframe width="420" height="315" src="http://www.youtube.com/embed/IytNBm8WA1c" frameborder="0" allowfullscreen></iframe>

Nice. now I'll take a plunkr from this Adobe article about writing AngularJS directives.

Here's the JS, slightly simplified:

var app = angular.module('cat-video-demo', []);

angular.module('cat-video-demo').directive('youtube', function() {
  return {
    restrict: 'E',
    template: '<iframe width="420" height="315" src="http://www.youtube.com/embed/IytNBm8WA1c" frameborder="0" allowfullscreen></iframe>'
  };
});

and now the HTML to use that would be the <youtube> element, as restricted by the 'E':

<youtube></youtube>

Maybe we want it to be somewhat responsive - StackOverflow search turns up this answer, so now we have this:

template: '<div style="height:400px;"><iframe style="overflow:hidden;height:100%;width:100%" width="100%" height="100%" src="http://www.youtube.com/embed/IytNBm8WA1c" frameborder="0" allowfullscreen></iframe>'

Now let's say we want to define the video code in the <youtube> element, say something like <youtube data-code="IytNBm8WA1c"></youtube>

If we wanted to write some valid HTML, we need to allow the directive to be used on an attribute:

restrict: 'A'

Or just plain remove that restrict property, since it will default to attribute. And change the HTML to

<div data-youtube></div>

Now if we want to pass in that Youtube code, we're going to do so by passing in the value. That's done so using the '@' - we don't need a binding to that variable since we won't be modifying it or anything (that would be the '='), we're just reading it off.

Here's the JS:

var app = angular.module('cat-video-demo', []);

angular.module('cat-video-demo').directive('youtube', function() {
  return {
    scope: { code:'@' },
    template: '<div style="height:400px;"><iframe style="overflow:hidden;height:100%;width:100%" width="100%" height="100%" src="http://www.youtube.com/embed/{{code}}" frameborder="0" allowfullscreen></iframe>'
  };
});

Here's the HTML now:

<body>
    <div data-youtube data-code='IytNBm8WA1c'></div>
</body>

If we don't mind writing invalid HTML, we can change the directive restriction to 'EA' to mean element or attribute, and just have this cleaner HTML:

<youtube code='IytNBm8WA1c'></youtube>

Bam!

Here's the plunkr.

Does it work with multiple instances of the directive?

Yes.

<body ng-controller="MainCtrl">
    <youtube code='IytNBm8WA1c'></youtube>
    <youtube code='wf_IIbT8HGk'></youtube>
</body>

Here's the same plunkr with twice as many cats.

Does it work with ng-repeat?

<youtube code='{{video}}' ng-repeat="video in ['IytNBm8WA1c', 'wf_IIbT8HGk']"></youtube>
Here's that plunkr.

High five Angular!

Originally written April 6, 2013.

Edited May 16, 2014 to clean up with better Angular practices. Originally, the code snippets created an angular module for the app and one for dependencies (as was in the Adobe article), which was overkill for this simpler demo. Also, a basically empty controller was removed as it was completely unnecessary for the demo. Plunkers updated respectively.