Building a Navbar Custom Directive

In this article by Fernando Monteiro, author of the book AngularJS Directives Cookbook, will see explain how to build a navbar directive and adapt it to an AngularJS application. We will also explore some basic functionalities of AngularJS directives. We will use a Yeoman generator to facilitate our work and illustrate how to organize your directory structure following the AngularJS best practices from community.

It is assumed that you have intermediate knowledge of developing applications using AngularJS and modern tools such as Yeoman, Bower, and Grunt. However, the following examples are exemplified didactically.

(For more resources related to this topic, see here.)

You can find more information about Yeoman at http://yeoman.io/.

Building a navbar directive

One of interface components most commonly used on websites and web applications are navigation menus. Although they are very simple, they are also very useful in any type of application.

In this example we will see how to build a navbar Directive and adapt it to an AngularJS application.

We will use a Yeoman generator to facilitate our work and illustrate how to organize your Directory Structure following the AngularJS best practices from community.First off you need to install the Yeoman Generator at: http://yeoman.io/

Getting ready

Open your Terminal window and type the following commands in the order they appear:

  1. To install the generator, use the following command:
    npm install generator-angm -g
  2. To create the application, use the following command:
    yo angm
  3. To create the modules, use the following command:
    yo angm:angm-module
  4. Use the name about for the module name.

    Repeat the last step to create the following modules: news, company, and navbar. We will discuss this in detail later.

  5. Now, test the boilerplate code. On your Terminal, type the following command:
    grunt dev

All the code will be compiled and your default browser will start with the welcome screen.

Remember, you must have administrator privileges to install the generator globally on your machine.

After all these commands are executed, we'll have created all the necessary directory structure for the directive example. At this point, you should have a directory structure similar to the following screenshot:

Generator-angm with modules created

The generator has created all the necessary code of an AngularJS application, following the best development practices. However, we will not go into details about all these files, as it is beyond the scope of this book.

Let's focus on the navbar folder and start building our navbar Directive. The navbar folder has the following files:

Filename

Description

navabar-test.js

Unity tests related to navbar module controller

navbar.html

Navbar view for the navbar module

navbarCtrl.js

Navbar controller

navbarRoute.js

AngularJS Route to Navbar view

Aside from the unit test file and the route file, the additional files are blank and just have the functions declarations.

An important point to note is that the generator compiles and injects all the code of controllers, routes and directives in the index.html file, as we can see in the following code.

<script src="/app/app.js"></script>

<script src="/app/home/homeRoute.js"></script>

<script src="/app/modules/about/aboutRoute.js"></script>

<script src="/app/modules/company/companyRoute.js"></script>

<script src="/app/modules/news/newsRoute.js"></script>

<script src="/app/home/homeCtrl.js"></script>

<script src="/app/modules/about/aboutCtrl.js"></script>

<script src="/app/modules/company/companyCtrl.js"></script>

<script src="/app/modules/navbar/navbarCtrl.js"></script>

<script src="/app/modules/news/newsCtrl.js"></script>

<script src="/app/modules/navbar/navbarDirective.js"></script>

We will replace the file navbarRoute.js by navbarDirective.js. For a better understanding we will follow some steps.

How to do it…

  1. Place the following code inside the navbarDirective.js file:
    'use strict';
    /**
    * @ngdoc function
    * @name app.directive:navbarDirective
    * @description
    * # navbarDirective
    * Directive of the app
    */
    angular.module('navbarexample')
    
    .directive('simpleNavbar', function () {
       return {
         restrict: 'E',
         templateUrl: 'app/modules/navbar/navbar.html',
        controller: 'NavbarCtrl',
       };
    });
  2. Place the following code inside the navbarCtrl.js:
    'use strict';
    
    /**
    * @ngdoc function
    
    * @name app.controller:navbarCtrl
    
    * @description
    
    * # navbarCtrl
    
    * Controller of the app
    
    */
    
    angular.module('navbar')
    
    .controller('NavbarCtrl', ['$scope', '$location', function
    ($scope, $location) {
    
    $scope.isActive = function(path){
    
       var currentPath = $location.path().split('/')[1];
    
       if (currentPath.indexOf('?') !== -1) {
    
         currentPath = currentPath.split('?')[0];
       }
       return currentPath === path.split('/')[1];
    
    };
    
    }]);

    As you've probably noticed there are several ways to create custom directives with AngularJS.

    The controller only checks the link state and returns a state if it is active with a route using the $location.path() function.

  3. Place the following HTML code inside the navbar.html file:
    <div class="navbar navbar-default">
    
    <div class="container">
    
       <ul class="nav navbar-nav">
    
         <li ng-class="{active:isActive('/')}"><a
         href="#!/">Home</a></li>
    
         <li ng-class="{active:isActive('#/about')}"><a
         href="#!/about">About</a></li>
    
         <li ng-class="{active:isActive('#/news')}"><a
         href="#!/news">News</a></li>
    
         <li ng-class="{active:isActive('#/company')}"><a
         href="#!/company">Company</a></li>
    
       </ul>
    
    </div>
    
    </div>

    The template gets the state sent by the controller and applies the selected CSS class to the link using the ng-class built in directive.

  4. At this stage, we have almost everything we need to build the directive. The final step is to add the navbardirective inside the HTML file. Open the index.html file inside the project root folder and add the following highlighted code to the markup:
    <!--Beginning-->
    
    <!-- Insert the Navbar -->
    
    <simple-navbar></simple-navbar>
    
    <section id="wrapper" class="container" scroll-to>
    
    <div class="view-slide-in" ng-view="main-app"></div>
    
    </section>
    
    <!--End-->
  5. Now, open your Terminal window and type the following command:
    grunt dev

    At this time, the code is compiled and your default browser opened on the welcome screen with the navbar directive on the top of the page, as shown in the following screenshot:

    Generator welcome screen with the navbar directive

You must have also noticed that we do not use any CSS to style our navbar. This is because the generator includes a copy of the Twitter bootstrap framework and we use only the already available classes from the framework.

<div class="navbar navbar-default">

<div class="container">
   ...
</div>
</div>

And everything happen inside the Directive markup:

<simple-navbar></simple-navbar>

As we mentioned about best practices on the previous example, let's see a good way to structure an AngularJS project.

Regardless of a code generator or boilerplate, you should choose to organize your content in a modular way by grouping by features.

The following screenshot shows a directory structure grouped by features:

Modular directory structure

You should group your modules into folders, and put all content on that functionality within these folders.

Controllers, Routes, Directives, Services, stylesheets, and everything that is related to the contents of the folder and functionality should have individual folders.

When we use some kind of generator or boilerplate, we can easily opt for one that lets the best structured code. In many cases, this becomes unfeasible, for example, in the case of applications in progress where the code was not properly structured.

Unfortunately, at the beginning of development with AngularJS, it was very common to use the directories structure grouped by function, that is, all controllers, services, routes and directives of the application were grouped into folders, each for a feature.

Over time, this has become a problem, especially in teams where all developers need to maintain the code. The tree files always tend to grow and the organization by functionality is much better than by function.

How it works…

A simple way to think about how to structure an application, you make an analogy those old toys to build something with blocks.

All applications with AngularJS have files and features in common. Some behaviors and components also tend to be very similar to many types of web applications with login screens, registration, forms, and much more.

A simple way to solve this is to use the following figure as a guide for implementing a well-organized structure that is easy to scale:

AngularJS application blueprint

Also, some IDE tools are very helpful when we need perform massive code refactoring. For the directives, it's always a good practice to have an extra folder inside the module folder to hold all the directives assets and templates. This is shown in the following figure:

Dashboard module detail

Working this way is very easy to delete and add new modules, using only a single directory from the entire application.

A suggestion that greatly helps the organization code is to avoid the utilization of prefixes already used by other directives as ng- or ui-.

Name your directives in the most intuitive way possible and follow the naming lowerCamelCase convention.

Summary

In this article we have seen how to build a navbar directive and adapt it to an AngularJS application.

Resources for Article:


Further resources on this subject:


You've been reading an excerpt of:

AngularJS Directives Cookbook

Explore Title
comments powered by Disqus