0

I need to create a menu that is able to handle multiple (not an exact number) levels of submenus

MainMenu.js (contains the menu property with all menu items)

class MainMenu {

    // @ngInject
    constructor() {


        this.menu = {
            name: 'Main menu',
            list: [
               {
                name: 'Sub menu lvl 1',
                list: [
                    {
                     name: 'Sub menu lvl 2',
                     list: [
                        {
                         name: 'Sub menu lvl 3'
                        } 
                     ]
                    }
                ]
               } 
            ]
        }



    }
}

export default function () {
    return {
        scope: {},
        templateUrl: 'path/to/MainMenu.tpl.html',
        replace: true,
        controller: MainMenu,
        controllerAs: 'mainMenuCtrl'
    };
};

This is the template html file (MainMenu.tpl.html)

<div>
    <nav id="menu" class="cm-menuwrapper">
        <ul class="cm-menu">
            <li ng-repeat="menuItem in mainMenuCtrl.menu.list">
                <a class="cursor-pointer" ng-click="mainMenuCtrl.someMethod(menuItem)"><span>{{menuItem.name}}</span></a>
                <sub-menu menu-item="menuItem" ng-if="menuItem.list"></sub-menu>
            </li>
        </ul>
    </nav>
</div>

SubMenu.js

class SubMenu {

    // @ngInject
    constructor() {

    }


}

export default function () {
    return {
        scope: {},
        templateUrl: 'path/to/SubMenu.tpl.html',
        replace: true,
        controller: SubMenu,
        controllerAs: 'subMenuCtrl',
        bindToController: {
            menuItem : "="
        }
    };
};

Sub menu html template file (SubMenu.tpl.html)

<ul class="cm-submenu">
    <li ng-repeat="submenu in subMenuCtrl.menuItem.list" ng-class="submenu.itemClass">
        <a class="cursor-pointer" ng-click="subMenuCtrl.someMethod(submenu)"><span>{{submenu.name}}</span></a>
        <sub-menu menu-item="submenu" ng-if="submenu.list"></sub-menu>
    </li>
</ul>

As you can see, I have placed <sub-menu ....> directivve into SubMenu.tpl.html and this seems to be causing some sort of infinite loop. The browser gets stuck with blank page and it consumes memory and cpu.

Any suggestions for this issue ?

1
  • 1
    You have to use $compile for recursive directives. Commented Nov 13, 2015 at 17:25

1 Answer 1

1

You have to hide your sub-directives from the initial compile by Angular. Add your recursive submenus dynamically, in the link function. Here is modified SubMenu.js:

/* @ngInject */ 
function submenuDirective($compile) {
  return {
    scope: {},
    templateUrl: 'path/to/SubMenu.tpl.html',
    replace: true,
    controller: SubMenu,
    controllerAs: 'subMenuCtrl',
    bindToController: {
        menuItem : "="
    },
    link: function(scope, elm) {
       const submenuNode = elm.find('.cm-submenu-list');
       submenuNode.append('<sub-menu menu-item="submenu" ng-if="submenu.list"></sub-menu>');
       $compile(submenuNode)(scope);
    }
  };
};

And do not forget to add wrapper into template:

<ul class="cm-submenu">
  <li ng-repeat="submenu in subMenuCtrl.menuItem.list" ng-class="submenu.itemClass">
    <a class="cursor-pointer" ng-click="subMenuCtrl.someMethod(submenu)"><span>{{submenu.name}}</span></a>
    <!-- submenu items will be rendered here later -->
    <div class="cm-submenu-list"></div>
  </li>
</ul>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.