[AngularJS] Dropdown Menu Using Directive


This post shows how to use AngularJS powerful directives to create dropdown menu without using any library (of course, except AngularJS).

Please first see:

Demo

JavaScript: See AngularJS: Developer Guide: Directives and AngularJS: API: $compile for how to write custom directives and API.

ngdropdown.js | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
'use strict';

angular.module('dropdown', []).
  directive('dropdown', ['$document', function($document) {
    return {
      restrict: 'A',
      transclude: true,
      scope: {
        classmenu: '@',
        classlink: '@',
        linktext: '@'
      },
      template: '<span ng-init="isShowMenu = false">' +
                  '<a ng-click="isShowMenu = !isShowMenu" ng-class="classlink" href="javascript:void(0);">{{ linktext }}</a>' +
                  '<span ng-show="isShowMenu" ng-click="isShowMenu = false" ng-class="classmenu" ng-style="menuStyle" ng-transclude></span>' +
                '</span>',
      link: function(scope, elm, attrs) {
        scope.menuStyle = { 'position': 'absolute' };

        elm.bind('mousedown', function() {
          // mousedown event is called earlier than click event
          scope.menuStyle['left'] =  elm.prop('offsetLeft') + 'px';
          scope.menuStyle['top'] =  (elm.prop('offsetTop') + elm.prop('offsetHeight') + 5) + 'px';
        });

        elm.bind('click', function(event) {
          event.stopPropagation();
        });

        $document.bind('click', function(e) {
          scope.isShowMenu = false;
          scope.$apply();
        });
      }
    };
  }]);

HTML: From line 11 to 15, the menu is placed inside a div element, the name dropdown of the custom directive is the attribute of the div element, and we use three other attributes (classlink, linktext, classmenu) to pass CSS class names and link text to the dropdown menu template in custom directive.

ngdropdown.html | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<!doctype html>
<html ng-app="dropdown">
<head>
  <meta charset="utf-8">
  <title>AngularJS dropdown menu</title>
  <link rel="stylesheet" type="text/css" href="style.css">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  </style>
</head>
<body style="padding: 5em;">

<div dropdown classlink="dropdownLink" linktext='click me' classmenu="dropdownMenu">
  <a href="http://www.google.com/">Google</a>
  <a href="http://www.facebook.com/">Facebook</a>
  <a href="http://www.amazon.com/">Amazon</a>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<script src="ngdropdown.js"></script>
</body>
</html>

CSS: Nothing special here. The same as you would do in a normal non-angularjs dropdown menu.

style.css | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.dropdownLink {
  text-decoration: none;
}

.dropdownMenu {
  border-radius: 5px;
  border-top-color: #C9D7F1;
  border-right-color: #36C;
  border-bottom-color: #36C;
  border-left-color: #A2BAE7;
  border-style: solid;
  border-width: 1px;
  z-index: 22;
  padding: 0;
  background-color: white;
  overflow: hidden;
  font-size: small;
  font-family: Arial;
  line-height: 2em;
  word-spacing: 0;
}

.dropdownMenu a {
  font-size: 1.25em;
  color: #00C;
  padding: .25em 2em .25em 1em;
  text-decoration: none;
  background: white;
  display: block;
  cursor: pointer;
}

.dropdownMenu a:hover {
  background: #00C;
  color: white;
}

Tested AngularJS version: 1.3.11, 1.1.5.


References:

[1]angularjs dropdown directive hide when clicked outisde - Stack Overflow