0

I am trying to create bootstrap navbar menus dynamically using Angular.

The source data for the menu comes from json which looks like below:

{   
"Menu": [
    {
        "title": "Individual",
        "url": "#",
        "subMenu": [{
            "title": "Individual Address",
            "url": "http://www.w3schools.com/html/default.asp",
            "subMenu": []
          }]
    },
    {
        "title": "Organisation",
        "url": "#",
        "subMenu": [{
            "title": "Organisation Address",
            "url": "http://www.w3schools.com/html/default.asp",
            "subMenu": []
        },{
            "title": "Organisation Contact",
            "url": "http://www.w3schools.com/html/default.asp",
            "subMenu": []
        },{
            "title": "Organisation Sector",
            "url": "http://www.w3schools.com/html/default.asp",
            "subMenu": []
        }]
    },

    {
        "title": "Return",
        "url": "http://www.w3schools.com/js/default.asp",
        "subMenu": []
    }
]
}

As you can see that there are nested items so we need to have dropdown menus in our navigation bar.

I have created a directive to generate the dynamic menus (I have used the directive found here as a starting point). The modified version of the directive looks like:

app.directive('tree', function ($compile) {
    return {
        restrict: 'E',
        terminal: true,
        scope: { val: '=', parentData:'=' },
        link: function (scope, element, attrs) {

          if (scope.val.subMenu !== undefined && scope.val.subMenu.length > 0) {
                template =      '<li class="dropdown"> '+
                              '  <a class="dropdown-toggle" data-toggle="dropdown" href="{{val.url}}">{{val.title}} '+
                              '  <span class="caret"></span></a> '+
                              '  <ul class="dropdown-menu"> '+
                              '   <div ng-repeat="item in val.subMenu"> '+
                              '     <tree val="item" parent-data="val.subMenu"></tree> '+
                              '   </div>'
                              '  </ul> '+
                              '</li> ';
            }
            else
            {
              template = '<li><a href="{{val.url}}">{{val.title}}</a></i> ';
            }
            var newElement = angular.element(template);
            $compile(newElement)(scope);
            element.replaceWith(newElement);            
        }
    }

Below is the html code where I am using this directive

<div class="container">
  <div class="row">
    <nav class="navbar navbar-default">
      <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
        <ul class="nav navbar-nav">
          <div ng-repeat="menu in menuFamily.Menu">
            <tree val="menu"></tree>
          </div>
        </ul>
      </div>
    </nav>
  </div>
</div>

The menus are generated but because I am using div tags for ng-repeat, the menus are not rendered properly. However, if I remove the div tags from the generated html everything works fine. So my question how can I achieve what I want without using div tags.

You can also find my sample code at plunker

P.S. I am new to Angular world and I have a very basic knowledge of directives.

1 Answer 1

1

If I understand your question correctly, there are two things you need to do:

Correct usage of ng-repeat

ng-repeat can be applied directly to your tree directive. Change

<div ng-repeat="...">
    <tree ...>
</div>

To

<tree ng-repeat="..." />

Both in your html file and in your directive's template property.

This will apply the proper styles to your menu.

Import Bootstrap js and initialize dropdowns

Because Angular will modify the DOM to add your dropdown's HTML, you need to manually initialize the dropdowns once they have been added.

Call $('.dropdown-toggle').dropdown() once your elements have been added.

Nevermind, just add the Bootstrap JS in your page, seems it properly initializes by itself.

<script src="http://code.jquery.com/jquery-2.1.4.min.js" data-semver="2.1.4" data-require="jquery@*"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>

Editied plunkr is here.

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.