MichalMazurek
MichalMazurek

Reputation: 81

Dynamicly added dropdown menu in AngularJS + Bootstrap

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...

Upvotes: 2

Views: 15607

Answers (2)

jwal
jwal

Reputation: 660

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.

Upvotes: 1

MichalMazurek
MichalMazurek

Reputation: 81

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.

Upvotes: 5

Related Questions