In the code below, inbetween the <body> tags are three <script> tags:

<!doctype html>
<html lang="en">
<head>
 <title></title>
</head> 
<body ng-app="todoListApp">
  <script type="text/javascript" src="vendor/angular.js" >
  <script type="text/javascript" src="scripts/app.js" >
  <script type="text/javascript" src="scripts/hello-world.js" >
</body>
</html>

Notice the sequence of the loading of the JS files: angular.js is loaded first, then app.js, and then finally the hello-world.js file. This is deliberate. This specific order is important because otherwise Angular wouldn't be able to find the module that other modules need at the right time. The end result are error messages that, depending on your familiarity or skill level with AngularJS, can either be rectified right away, or can leave you pondering for awhile until you head on to Stack Overflow for answers.

Moving on.

This is the content of app.js:

angular.module('todoListApp', []);

The hello-world.js is our user-defined directive, and these are its contents:

angular.module('todoListApp')
       .directive( 'helloWorld', function() {
         return { template: "This is the hello world directive!" };
       });

What this tells us is, it has a directive named helloWorld, and when the directive is invoked, it returns the sentence This is the hello world directive!.

Notice that there is no empty array ([]) after the todoListApp (unlike in app.js), this is because we don't want Angular to create a new module. We just want it to look for and use the already existing todoListApp module in app.js.

So now that we have both the app.js and hello-world.js files fleshed out, the remaining thing to do is to invoke the directive in index.html. This is how to invoke the directive (on line 8):

<!doctype html>
<html lang="en">
<head>
 <title></title>
</head> 
<body ng-app="todoListApp">

  <hello-world></hello-world>
  
  <script type="text/javascript" src="vendor/angular.js" >
  <script type="text/javascript" src="scripts/app.js" >
  <script type="text/javascript" src="scripts/hello-world.js" >
</body>
</html>

This is how the directive renders:

But I must admit, the frontend developer in me balks upon seeing the <hello-world> tag there. It just looks so out of place.

Invoking the directive through tag attributes

Thankfully, AngularJS makes it very flexible. So I can actually do this and get the same result:

<div hello-world></div>

There, everything's alright in my frontend developer world now.

Restricting the directive to be invoked only as an element

However, the programmer in me welcomes the non-standard tags though because I think it really makes the intention much clearer. It fits well with the programmer's mindset.

AngularJS makes it possible to enforce the rule regarding invocation of directives to restrict it to elements only:

angular.module('todoListApp')
       .directive('helloWorld', function() {
         return {
           template: "This is the hello world directive!",
           restrict: "E"
         };
       });

So, when it's enforced like above and we invoke the directive as an attribute, this is the result:

It is empty. The template disappeared.

But, if we invoke it as an element:

The result is as expected. We get the templates back:

Please leave your questions or comments below.