Dynamicly added dropdown menu in AngularJS + Bootstrap

15,570

Solution 1

Solved!

I've finally made it with ng-if and ng-repeat-start. With help in comments, I've found that ng-class does not run directives.

    <ul class="navbar-nav nav navbar-left">
        <span ng-repeat-start="menu_element in globalMenu"></span>
        <li ng-if="menu_element.dropdown !== undefined">
              <a ng-href="{{menu_element.href}}" class="dropdown-toggle">
                  {{menu_element.label}}
                  <b class="caret" ></b>
              </a>
              <ul class="dropdown-menu">
                  <li ng-repeat="sub_element in $parent.menu_element.dropdown">
                      <a ng-href="{{sub_element.href}}">{{sub_element.label}}</a>
                  </li>
              </ul>
        </li>
        <li ng-if="menu_element.dropdown === undefined">
              <a ng-href="{{menu_element.href}}">
                {{menu_element.label}}
              </a>
        </li>
        <span ng-repeat-end></span>
    </ul>

Working example on Plnkr. Something happened with the css on Plunker, yesterday it was working... but still it works.

Solution 2

Nice, this helped me along the way. I've a slight variation on your theme.

<ul class="nav navbar-nav">
  <li ng-repeat='link in menu track by $index' ng-class='[{dropdown:link.sub}]'>
    /* normal menu */
    <a ng-if='!link.sub' ng-bind='link.id' ng-click='jump(link.to)'></a>
    /* dropdown menu */
    <a ng-if='link.sub' class="dropdown-toggle" data-toggle="dropdown">
      <span ng-bind='link.id'></span>
      <ul class="dropdown-menu inverse-dropdown">
        /* and repeat for the submenu */
        <li ng-repeat='slink in link.menu track by $index'>
          <a ng-bind='slink.id' ng-click='jump(slink.to)'></a>
        </li>
      </ul>
    </a>
  </li>
</ul>

My menu array is a list of

{id:'name', to:n}

where n points to an array listing some html I push into the page. When there is a sub menu the menu array element is

{id:'name', sub:true, menu:[{id:'name', to:n}, etc.]}

I tried ui-bootstrap but never got my head around it.

Share:
15,570
MichalMazurek
Author by

MichalMazurek

Updated on June 07, 2022

Comments

  • MichalMazurek
    MichalMazurek almost 2 years

    I'm writing a module that will create a dynamic menu on the fly. How to run a directive after adding new <li> with css class dropdown which is also added by ng-class.
    The code:

    angular.module('myapp', ['ui.bootstrap'])
    .factory("menuService", ["$rootScope", function($rootScope) {
        "use strict";
    
        return { 
            menu: function() {
                $rootScope.globalMenu;
            },    
            setMenu: function(menu) {
                $rootScope.globalMenu = menu;
            }
        };
    
    }])
    .controller("MainController", ["$scope", "menuService",
        function($scope, menuService){
    
            menuService.setMenu([{href:"#", label:"Dropdown",
                                    dropdown:[{href:"/edit", label:"Edit"}]},
                                 {href:'/', label:'test'}]);
    
            $scope.bodyText = "Some text";
    
    
        }]);
    

    This is the code in html

        <ul class="navbar-nav nav navbar-left">
            <li ng-repeat="menu_element in globalMenu" ng-class="{dropdown: menu_element.dropdown != undefined}">
                <a ng-href="{{menu_element.href}}" ng-class="{'dropdown-toggle': menu_element.dropdown != undefined}">
                    {{menu_element.label}}
                    <b class="caret" ng-if="menu_element.dropdown != undefined"></b>
                </a>
                <ul ng-if="menu_element.dropdown != undefined" class="dropdown-menu">
                    <li ng-repeat="sub_element in $parent.menu_element.dropdown">
                        <a ng-href="{{sub_element.href}}">{{sub_element.label}}</a>
                    </li>
                </ul>
            </li>
        </ul>
    

    Link to plunker: http://plnkr.co/edit/pgH35mmsjLJqV4yJuSYq?p=preview

    So what I want to do is the same or similar as for jQuery, there I would run $("li.dropdown").dropdown() after adding whole ul>li blocks. I'm new to Angular and I want to make this in the angular way.

    I read about directives, how to use them. But I couldn't find how to apply directive in runtime. I've read about transclude: element in a directive (ui.bootstrap.dropdownToggle) doesn't have it enabled. I'm sure that there is a easy way, but couldn't find it myself...