下拉子菜单和角度指令中的递归

Dropdown submenu and Recursion in angular directives

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

我需要一个从角度树json结构创建的引导菜单。这两个堆栈溢出答案分别处理每个问题。我需要将它们组合在一起:

  • 缺少引导程序 3 下拉子菜单
  • 角度指令中的递归

引导 3 下拉子菜单(小提琴(

示例标记

<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display: block; position: static; margin-bottom: 5px; *width: 180px;">
  <li class="menu-item dropdown dropdown-submenu">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Level 1</a>
    <ul class="dropdown-menu">
      <li class="menu-item ">
        <a href="#">Link 2</a>
      </li>
      <li class="menu-item dropdown dropdown-submenu">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Level 2</a>
        <ul class="dropdown-menu">
          <li>
            <a href="#">Link 3</a>
          </li>
          <li class="menu-item dropdown dropdown-submenu">
            <a ref="#" class="dropdown-toggle" data-toggle="dropdown">Level 3</a>
            <ul class="dropdown-menu">
              <li>
                <a href="#">Link 4</a>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

.CSS

.dropdown-submenu {
  position: relative;
}
.dropdown-submenu>.dropdown-menu {
  top: 0;
  left: 100%;
  margin-top: -6px;
  margin-left: -1px;
  -webkit-border-radius: 0 6px 6px 6px;
  -moz-border-radius: 0 6px 6px 6px;
  border-radius: 0 6px 6px 6px;
}
.dropdown-submenu:hover>.dropdown-menu {
  display: block;
}
.dropdown-submenu>a:after {
  display: block;
  content: " ";
  float: right;
  width: 0;
  height: 0;
  border-color: transparent;
  border-style: solid;
  border-width: 5px 0 5px 5px;
  border-left-color: #cccccc;
  margin-top: 5px;
  margin-right: -10px;
}
.dropdown-submenu:hover>a:after {
  border-left-color: #ffffff;
}
.dropdown-submenu.pull-left {
  float: none;
}
.dropdown-submenu.pull-left>.dropdown-menu {
  left: -100%;
  margin-left: 10px;
  -webkit-border-radius: 6px 0 6px 6px;
  -moz-border-radius: 6px 0 6px 6px;
  border-radius: 6px 0 6px 6px;
}

角度指令中的递归(小提琴(

module.factory('RecursionHelper', ['$compile', function($compile){
    var RecursionHelper = {
        compile: function(element){
            var contents = element.contents().remove();
            var compiledContents;
            return function(scope, element){
                if(!compiledContents){
                    compiledContents = $compile(contents);
                }
                compiledContents(scope, function(clone){
                    element.append(clone);
                });
            };
        }
    };
    return RecursionHelper;
}]);
module.directive("tree", function(RecursionHelper) {
    return {
        restrict: "E",
        scope: {family: '='},
        template: 
            '<p>{{ family.name }}</p>'+
            '<ul>' + 
                '<li ng-repeat="child in family.children">' + 
                    '<tree family="child"></tree>' +
                '</li>' +
            '</ul>',
        compile: function(element) {
            return RecursionHelper.compile(element);
        }
    };
});

我尝试合并两者(小提琴(

module.directive("tree", function(RecursionHelper) {
  return {
    restrict: "E",
    scope: {
      family: '='
    },
    template: '<a href="#" ng-attr-class="{{family.children.length != 0 && ''dropdown-toggle''}}" ng-attr-data-toggle="{{ family.children.length != 0 && ''dropdown''}}">{{ family.name }}</a>' +
      '<ul class="dropdown-menu" ng-if="family.children.length!=0">' +
      '<li ng-attr-class="{{family.children.length != 0 && ''menu-item dropdown dropdown-submenu''|| ''menu-item''}}" ng-repeat="child in family.children">' +
      '<tree family="child"></tree>' +
      '</li>' +
      '</ul>',
    compile: function(element) {
      return RecursionHelper.compile(element);
    }
  };
});

如您所见,我的尝试不起作用。

问题

使用 Chrome 开发人员工具,我发现 Bootstrap 子菜单无法与在元素中包含额外的标签相处li

因此,以下HTML代码(在li之后添加<data-some-random-tag>(不起作用(小提琴(。

<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display: block; position: static; margin-bottom: 5px; *width: 180px;">
  <li class="menu-item dropdown dropdown-submenu">
    <data-some-random-tag><!-- <---- **this tag was added** -->
      <a href="#" class="dropdown-toggle" data-toggle="dropdown">Level 1</a>
      <ul class="dropdown-menu">
        <li class="menu-item ">
          <a href="#">Link 2</a>
        </li>
        <li class="menu-item dropdown dropdown-submenu">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown">Level 2</a>
          <ul class="dropdown-menu">
            <li>
              <a href="#">Link 3</a>
            </li>
            <li class="menu-item dropdown dropdown-submenu">
              <a ref="#" class="dropdown-toggle" data-toggle="dropdown">Level 3</a>
              <ul class="dropdown-menu">
                <li>
                  <a href="#">Link 4</a>
                </li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </data-some-random-tag>
  </li>
</ul>

因此,tree标签正在破坏引导子菜单。我认为将指令类型更改为 html 注释可以解决此问题。我知道我可以更改指令

<span my-dir="exp"></span>

<!-- directive: my-dir exp -->

<tree family="child"></tree><!-- directive: tree family child -->不起作用。也尝试过<!-- directive: tree family=child --><!-- directive: tree family="child" -->

我对其他可能的解决方案持开放态度。

我跟进了这个:是否可以使用角度制作树视图?

小提琴http://jsfiddle.net/82trw21a/1/

<script type="text/ng-template" id="tree_item_renderer.html">
  <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{data.name}}</a>
  <ul class="dropdown-menu">
    <li ng-if="data.children.length != 0" class="menu-item dropdown dropdown-submenu" ng-repeat="data in data.children" ng-include="'tree_item_renderer.html'"></li>
    <li ng-if="data.children.length == 0" class="menu-item" ng-repeat="data in data.children" ng-include="'tree_item_renderer.html'"></li>
  </ul>
</script>
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display: block; position: static; margin-bottom: 5px; *width: 180px;">
  <li class="menu-item dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Menu<b class="caret"></b></a>
    <ul class="dropdown-menu" ng-app="Application" ng-controller="TreeController">
      <li class="menu-item dropdown dropdown-submenu" ng-repeat="data in tree" ng-include="'tree_item_renderer.html'"></li>
    </ul>
  </li>
</ul>

角:

angular.module("myApp", []).
controller("TreeController", ['$scope', function($scope) {
  $scope.delete = function(data) {
    data.children = [];
  };
  $scope.add = function(data) {
    var post = data.children.length + 1;
    var newName = data.name + '-' + post;
    data.children.push({
      name: newName,
      children: []
    });
  };

  $scope.tree = [{
    name: "Level1",
    children: [{
      name: "Link1",
      children: []
    }, {
      name: "Level2",
      children: [{
        name: "Link3",
        children: []
      }, {
        name: "Level3",
        children: [{
          name: "Link4",
          children: []
        }]
      }]
    }]
  }];
}]);