多级菜单的Angular指令

时间:2016-01-22 10:49:51

标签: javascript angularjs

我有这个菜单结构,我想创建一个以递归方式生成列表的角度指令。

    $scope.Items = [
     {
      title: 'Spaces',
      icon: 'icon-layers',
      href: 'javascript:;',
      isActive: path === '/Spaces',
      subitems: 
       [{
        title: 'OpenSpaces',
        icon: 'icon-layers',
        href: '#/OpenSpaces',
        isActive: path === '/OpenSpaces',
        subitems: 
          [{
            title: 'OpenSpaces2',
            icon: 'icon-layers',
            href: '#/OpenSpaces2',
            isActive: path === '/OpenSpaces2',
          }]
       }]
     }, 
     {
      title: 'Meeting',
      icon: 'icon-layers',
      href: '#/meeting',
      isActive: path === '/meeting'
     }];

我创建了一个生成正确html的函数。如何将此函数关联到指令中?所以我可以写入html指令标签。

这是功能:

   angular.forEach(dashitems, function(value, key) {
            $scope.menu+="<li class='nav-item'>";
            if(value.hasOwnProperty('subitems')){


               $scope.menu+="<a href='javascript:;' class='nav-link nav-toggle'>"+
                  "<i class='"+value.icon+"'></i>"+
                  "<span class='title'>"+value.title+"</span>"+
                  '<span class="arrow open"></span>'+
                   "</a>";
               $scope.menu += '<ul class="sub-menu">';
              printList(value.subitems);
               $scope.menu += "</ul>";
            }else{
                 $scope.menu+=' <a href="'+value.href+'" >'+
                          '<i class="'+value.icon+'"></i>'+
                          '<span class="title">'+value.title+'</span>'+
                      '</a>';                  
            }
            $scope.menu+="</li>";
        });



        return $scope.menu;
    }

有什么建议吗?谢谢!

3 个答案:

答案 0 :(得分:0)

在我看来,你在你的代码中误认为“ul”和“li”(如果不是,请纠正我)并且我改变了它们。

除此之外,我不太清楚这部分是什么意思:

    $scope.menu += '<ul class="sub-menu">';
    printList(value.subitems);
    $scope.menu += "</ul>";

但是如果你想重复“ul”并在里面重复一些“li”,你为什么不能使用ng-repeat?

我认为它会像这样(我从代码中复制了大部分内容):

<ul ng-repat="item in Items" class='nav-item'>
    <a href='javascript:;' class='nav-link nav-toggle'>
        <i class="{{item.icon}}"></i>
        <span class='title'>{{item.title}}</span>
        <span class="arrow open"></span>
    </a>
    <li class="sub-menu" ng-if="item.subitems" ng-repeat="subs in item.subitems">
        //some data using subs.title and other stuff...
    </li>
</ul>

我认为即使是ng-if也没有必要。 无论如何,如果你想要的话,你可以将ng-repeats嵌套在彼此中......

希望这是有帮助的

答案 1 :(得分:0)

angular
  .module('App').directive('menuBar', function() {
    return {
  replace: true,
  restrict: 'E',
  controller: ['$scope','$location',function ($scope,$location) {

     //function
   }],
    link: function(scope, elem, attrs) {

           elem.append("<ul>"+scope.printList(scope.dashitems)+"</ul>");
        }
  }
  });

答案 2 :(得分:0)

This我更倾向于解决您的问题。

我建议您创建一个接受 blueprint 对象的服务来生成 raw html - 后者又包含一个自定义指令。

自定义指令

这是为每个列表项定义指令的可能方法;请注意,对于指令定义的范围对象,您将传递所需信息,例如列表项的titlehreficon

app.directive('navItem', function() {
return {
  restrict: 'E',
  transclude: true,
  replace: true,
  scope: {
      title: '@',
      href: '@',
      icon: '@'
    },
  template: '<li><a href="{{ href }}">'
   + '<i class="{{ icon }}"></i><span>{{ title }}</span></a>'
   + '<ul class="sub-menu" ng-transclude></ul></li>'
  };
});

指令生成服务

递归的服务,创建HTML节点,稍后将其编译为指令定义:

app.service('NavBarCreator', [function() {
var rawHtml = angular.element("<div />");

return function(itemJson) {
  recur(itemJson, rawHtml);
  return rawHtml.html();
};

function recur(items, parent) {
  angular.forEach(items, function(item, i) {
    //create the directive HTML node with the passed in attributes to be used in the `scope` object of the directive
    var itemHtml = angular.element('<nav-item />');

     itemHtml.attr('title', item.title);
     itemHtml.attr('href', item.href);
     itemHtml.attr('icon', item.icon);

      parent.append(itemHtml);
      //repeat the same if the item has any subitems
      if (item.subitems && item.subitems.length > 0) {
        recur(item.subitems, itemHtml);
      }
    })
  };
}]);

<强> 注意:

我还实现了一个包装器指令,该指令实现了上述服务,并负责为菜单项使用 blueprint JSON,以及{{ 1}}它的内容,以便触发它的子项的前面定义的指令定义。

这完全是可选的,因为您可以在控制器中应用相同的逻辑。但是,它可能有助于保持一些东西清洁。