多级菜单的角度指令

Angular directive for multi level menu

本文关键字:指令 菜单 多级      更新时间:2023-09-26

我有这个菜单结构,我想创建一个以 angular 递归方式制作列表的指令。

    $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;
    }

有什么建议吗?谢谢!

在我看来

,您在代码中弄错了"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 重复......

希望对您有所帮助

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>");
        }
  }
  });

这就是 我更愿意解决您的问题的方式。

我建议您创建一个接受蓝图对象来生成原始html的服务 - 这反过来又包含自定义指令。

自定义指令

下面是为每个列表项定义指令的可能方法;请注意,对于指令定义的 scope 对象,您传递的是所需的信息,例如列表项的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);
      }
    })
  };
}]);

注意:

我还实现了一个包装器指令,它实现了上述服务,并负责使用菜单项的蓝图 JSON 以及$compiling其内容,以便触发之前为其子项定义的指令定义。

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