Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive menu directive

I'm trying to do a recursive menu with angularJS, but I keep getting the fallowing error: Maximum call stack size exceeded

My directives:

angular.module("application").directive("navigation", [function () {
            return {
                restrict : 'E',
                replace : true,
                scope : {
                    menu : '='
                },
                template : '<ul><navigation-item ng-repeat="item in menu" submenu="item"></navigation-item></ul>',
                link : function ($scope, elem, attrs) {}
            }
        }
    ]);


angular.module("application").directive("navigationItem", [function () {

            return {
                restrict : 'E',
                replace : true,
                scope : {
                    submenu : '='
                },
                template : '<li>{{ submenu }}<navigation menu="submenu.Children"></navigation></li>',
                link : function ($scope, elem, attrs) {}
            }
        }
    ]);

My controller:

app.controller('myController', ['$scope', function (ng) {
        ng.menu = [{
            Id : 1,
            Nome : "Contact",
            Children : [{
                Nome : "Testing",
                Children : []
            }]
        }];
    }
]);

Here's how I'm using it:

<navigation menu="menu"></navigation>

http://jsfiddle.net/7sq3n/

like image 722
WeaselBr Avatar asked Nov 13 '13 19:11

WeaselBr


2 Answers

There's 2 things here:

  1. You don't need 2 directives
  2. I had suspected that you would need to use the directive's compile function to get this to work since you're using the directive itself inside its own template, you'll also need to use the injectable $compile

I've used the ngIf directive in the template, you don't have to I just wanted to let you know and to warn you that you need to use AngularJS 1.1.5+ in order to use that directive.

Here's a JSFiddle I got working: http://jsfiddle.net/mikeeconroy/7sq3n/6/

.directive("navigation", ['$log','$compile',function ($log,$compile) {

    return {
        restrict: 'E',
        replace: true,
        scope: {
            menu: '='
        },
        template: '<ul><li ng-repeat="item in menu">{{item.Name}}<span ng-if="item.Children.length > 0"><navigation menu="item.Children"></navigation></span></li></ul>',
        compile: function (el) {
            var contents = el.contents().remove();
            return function(scope,el){
                $compile(contents)(scope,function(clone){
                    el.append(clone);
                });
            };
        }
    };

I cobbled this together with a little help from here: Recursion in Angular directives

UPDATE: http://jsfiddle.net/mikeeconroy/Z6sG9/2/ Solves multiple root element problem

like image 90
m.e.conroy Avatar answered Nov 16 '22 09:11

m.e.conroy


Dynamic, recursive navigation menu (navbar) using dynamic data with Angular & Bootstrap.

http://plnkr.co/edit/YqGcmcH6VQqr3rxOswnb

    <div ng-app="headerMenuApp">
    <div ng-controller="headerMenuListController">
        <nav id="headerNavigationMenuContainer" class="navbar navbar-default">
            <div class="container-fluid">

                <!-- Non-collapsing right-side menu items -->
                <div class="navbar-header pull-right">
                    <ul class="nav pull-left navbar-nav text-nowrap">
                        <li class="dropdown pull-right">
                            <a href="#" class="dropdown-toggle navbar-icon" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-question-circle"></i> &nbsp; Help <span class="caret"></span></a>
                            <ul class="dropdown-menu" role="menu">
                                <li><a href="#">Live Chat</a></li>
                                <li><a href="#">Help Topics</a></li>
                            </ul>
                        </li>
                    </ul>
                </div>

                <!-- Collapsing left-side menu items -->
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed pull-left" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar" ng-init="navCollapsed = true" ng-click="navCollapsed = !navCollapsed">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="#">Logo</a>
                </div>

                <div id="navbar" class="collapse navbar-collapse" ng-class="!navCollapsed && 'in'">
                    <ul class="nav navbar-nav text-nowrap">
                        <leaf ng-repeat='leaf in tree' leaf='leaf'></leaf>
                    </ul>
                </div>

            </div>
        </nav>
    </div>
</div>
like image 27
Jake H Avatar answered Nov 16 '22 09:11

Jake H