robin
robin

Reputation: 1925

Issue With Dynamic menu directive in Angular JS

I am creating a dynamic menu using angular JS. My directive is like

restrict : 'EA',
replace : true,
scope :{menu : "=menu"},
compile: function(element, attributes) {
    var linkFunction = function($scope, element, attributes){
              element.empty();
              element.append('<div id="cssmenu"><ul><div id="menu-button">Menu</div>');
              for (i = 0;i<$scope.menu.length;i++){
              element.append("<li class='has-sub'><a href='#'>  <span>"+$scope.menu[i].name+"</span></a></li>");
                    }
              element.append('</ul></div>');
                }
          return linkFunction;
     }

My HTML code is like

<div  ng-app="mainApp" ng-controller="MenuController">
  <my-menu menu="menu"></my-menu>
</div>

I am expecting an the resource to be generated like

  <div id="cssmenu">
    <ul>
    <div id="menu-button">Menu</div>
                <li class='has-sub'><a href='#'><span>Home</span></a></li>
                <li class='has-sub'><a href='#'><span>About</span></a></li>
            </ul>
</div>

But the current one generated is like

<my-menu menu="menu" class="ng-isolate-scope">
<div id="cssmenu">
<ul>
<div id="menu-button">Menu</div>
</ul>
</div>
<li class="has-sub"><a href="#"><span>Home</span></a></li>
<li class="has-sub"><a href="#"><span>Contact</span></a></li>
</my-menu>

Issues I am facing

1) Why is the my-menu tag getting displayed ?

2) Why is the and tags getting closed before the tags are printed?

Also Please find the link to Plunker

Upvotes: 3

Views: 735

Answers (2)

bluetoft
bluetoft

Reputation: 5443

You are appending things incorrectly to your element. You append elements to elements with jQuery, and jQuery lite, which is what is included with angularjs. You were using it like a string builder. Here is the modifications which work as desired (code modified from your plnkr):

var linkFunction = function($scope, e, attributes){
                var element = angular.element('<ul />');;
                for (i = 0;i<$scope.menu.length;i++){
                    var li = angular.element('<li><a href="#">'+$scope.menu[i].name+'</a></li>');

                    if($scope.menu[i].subList.length > 0 ){
                        var subList = angular.element('<ul />')

                        for(j=0;j<$scope.menu[i].subList.length;j++){
                             var subLi = angular.element('<li><a href="#">'+$scope.menu[i].subList[j].name+'</a></li>');
                             subList.append(subLi);
                        }
                        li.append(subList);
                    }
                    element.append(li);
                }
                e.replaceWith(element);
        }

This produces the following markup:

<div ng-app="MenuDirective" ng-controller="MenuController" class="ng-scope">

        <ul>
            <li>
                <a href="#">Home</a>
                <ul>
                    <li>
                        <a href="#">Home1</a>
                    </li>
                    <li>
                        <a href="#">Home2</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">Contact</a>
                <ul>
                    <li>
                        <a href="#">Contact1</a>
                    </li>
                    <li>
                        <a href="#">Contact2</a>
                    </li>
                </ul>
            </li>
        </ul>
    </div>

Which is valid html markup. (your desired output is not due to the div as a child of the ul) and renders like so:

  • Home
    • Home1
    • Home2
  • Contact
    • Contact1
    • Contact2

Plnkr

So as answers to your 2 questions:

1) Why is the my-menu tag getting displayed ?

empty() removes the CONTENTS of your element, it doesn't make your element into nothing. Also, your element isn't replaced because there is no template supplied either by template property or by templateUrl property and thus there is nothing to replace your tag with.

2) Why is the and tags getting closed before the tags are printed?

Your tags are getting inserted in the wrong places because you're adding strange html nodes to the end of your root html node, not directly into the previous element you appended

Upvotes: 1

Mike Vranckx
Mike Vranckx

Reputation: 5577

You aren't allowed to add a <div> element as child from the <ul>.

Remove the <div id="menu-button">Menu</div>

Upvotes: 0

Related Questions