3

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

2
  • Not sure on the behavior you're seeing, however I wonder why you're using the compile function vs just using a template? I don't see anything a simple template can't handle here... Commented Aug 18, 2015 at 5:56
  • Actually what I need a function which will create template dynamically. Commented Aug 18, 2015 at 6:18

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

Comments

0

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

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

1 Comment

it doesn't change anything

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.