AngularJS multilevel dropdown menu for a menu structure generated from a recursive directive AngularJS multilevel dropdown menu for a menu structure generated from a recursive directive angularjs angularjs

AngularJS multilevel dropdown menu for a menu structure generated from a recursive directive


This is what I use and it has a lot of extra functionality that is pretty sweet.See the usage $scope.menu and what happens when you expand the dropdown - you can put in headers, dividers, and even attach click functions. Note that you can nest as many ul as you want, and though toggle does work, it's useless since clicking to open a submenu will hide its parent. As far as I know, you would need to create your own javascript handler or custom css using hovers if you want deeper nesting in the menu.

Live demo here (click).

<nav>  <div menu="menu"></div> <!-- the element here doesn't matter --></nav>

js:

var app = angular.module('myApp', ['ui.bootstrap']);app.directive('menu', function() {  return {    restrict: 'A',    scope: {      menu: '=menu',      cls: '=ngClass'    },    replace: true,    template: '<ul><li ng-repeat="item in menu" menu-item="item"></li></ul>',    link: function(scope, element, attrs) {      element.addClass(attrs.class);      element.addClass(scope.cls);    }  };});app.directive('menuItem', function($compile) {  return {    restrict: 'A',    replace: true,    scope: {      item: '=menuItem'    },    template: '<li active-link><a href={{item.href}}>{{item.title}}</a></li>',    link: function (scope, element, attrs) {      if (scope.item.header) {        element.addClass('nav-header');        element.text(scope.item.header);      }      if (scope.item.divider) {        element.addClass('divider');        element.empty();      }      if (scope.item.submenu) {        element.addClass('dropdown');        var text = element.children('a').text();        element.empty();        var $a = $('<a class="dropdown-toggle">'+text+'</a>');        element.append($a);        var $submenu = $('<div menu="item.submenu" class="dropdown-menu"></div>');        element.append($submenu);      }      if (scope.item.click) {        element.find('a').attr('ng-click', 'item.click()');      }      $compile(element.contents())(scope);    }  };});app.controller('myCtrl', function($scope) {  $scope.menu = [    {      "title": "Home",      "href": "#"    },    {      "title": "About",      "href": "about"    },    {      "title": "History",      "href": "about/history"    },    {      "title": "Contact",      "href": "contact"    },    {      "title": "Other things - in a list. (Click here)",      "submenu": [        {          "header": "Sample Header"        },        {          "title": "Some Link",          "href": "some/place"        },        {          "title": "Another Link",          "href": "some/other/place"        },        {          "divider": "true"        },        {          "header": "Header 2"        },        {          "title": "Again...a link.",          "href": "errrr"        },        {          "title": "Nest Parent",          "submenu": [            {              "title": "nested again",              "href": "nested/again"            },            {              "title": "me too",              "href": "sample/place"            }          ]        }      ]    }  ];});

Update for nested dropdown:

Live demo here (click).

.dropdown-menu .dropdown-menu {  margin: 0;  left: 100%;  top: -5px;}.dropdown-menu li:hover .dropdown-menu {  display: block;}