Javascript AngularJS多级下拉菜单,用于递归指令生成的菜单结构

Javascript AngularJS多级下拉菜单,用于递归指令生成的菜单结构,javascript,angularjs,angularjs-directive,angularjs-bootstrap,Javascript,Angularjs,Angularjs Directive,Angularjs Bootstrap,我这里有一点腌菜。 我必须从Web服务调用中获取多级导航菜单 因为我的导航菜单可以有无限多的子菜单,所以我不得不使用递归指令来构建父/子导航结构。 现在我正试图找出如何将其转换为功能性的dropmenu结构。 我在看angularui的bootstrap,他们有一个 下拉切换,它有一些基本的下拉菜单功能,但是 我使用了一个递归指令,我的菜单结构已经有了angularjs生成的css 与之相关的课程。angularjs引导下拉菜单 css类与我的angularjs生成的类不同…看 <ul&g

我这里有一点腌菜。 我必须从Web服务调用中获取多级导航菜单

因为我的导航菜单可以有无限多的子菜单,所以我不得不使用递归指令来构建父/子导航结构。 现在我正试图找出如何将其转换为功能性的dropmenu结构。 我在看angularui的bootstrap,他们有一个 下拉切换,它有一些基本的下拉菜单功能,但是 我使用了一个递归指令,我的菜单结构已经有了angularjs生成的css 与之相关的课程。angularjs引导下拉菜单 css类与我的angularjs生成的类不同…看

<ul>
    <li ng-repeat="parent in parents" class="ng-scope">
        <recursive-list-item on-node-click="onNodeClickFn(node)" parent="parent" class="ng-isolate-scope ng-scope">
            <a data-ng-click="onNodeClick({node: parent})" href="javascript:void(0)" class="ng-scope ng-binding">Clothes</a>
            <!-- ngIf: parent.children.length > 0 -->
            <ul data-ng-if="parent.children.length &gt; 0" class="ng-scope">
                <!-- ngRepeat: child in parent.children -->
                <li ng-repeat="child in parent.children" class="ng-scope">
                    <recursive-list-item data-on-node-click="onNodeClickFn(node)" data-parent="child" class="ng-isolate-scope ng-scope">
                        <a data-ng-click="onNodeClick({node: parent})" href="javascript:void(0)" class="ng-scope ng-binding">Gortex Jackets</a>
                        <!-- ngIf: parent.children.length > 0 -->
                    </recursive-list-item>
                </li>
                <!-- end ngRepeat: child in parent.children -->
                ...
                ...
                ...
            </ul>
        </recursive-list-item>
    </li>
    <!-- end ngRepeat: child in parent.children -->
...
...
</ul>
它是从官方的引导css文件中获得的。 不知道为什么它不可见。 不确定它是否有用,但这里是ul之后下一个li元素的css

*, *:before, *:after {
    -moz-box-sizing: border-box;
}
*, *:before, *:after {
    -moz-box-sizing: border-box;
}
.dropdown {
    position: relative;
}
.dropup, .dropdown {
    position: relative;
}
li {
    line-height: 20px;
}
*, *:before, *:after {
    -moz-box-sizing: border-box;
}
请记住,当我添加angularui引导所需的css标记时,您必须转到plunker页面才能看到更新的代码。 要查看不可见的导航元素,您需要像Firebug这样的东西来查看DOM

下面是我的更新中的一些html最终输出(来自DOM)的示例,用于尝试使用angularui引导css类

...
<li ng-repeat="child in parent.children" class="dropdown ng-scope">
            <recursive-list-item data-on-node-click="onNodeClickFn(node)" data-parent="child" class="ng-isolate-scope ng-scope">
            <a class="dropdown-toggle ng-scope ng-binding" href="javascript:void(0)">Kids Clothes</a>
...
。。。
  • ...

  • 我怀疑angularui引导库不工作的原因是“recursive list item..”元素是“li”元素的子元素,而“a”元素的父元素。我的直觉正确吗?

    这就是我使用的,它有很多额外的功能,非常好用。 查看用法
    $scope.menu
    ,以及展开下拉列表时会发生什么-您可以放入标题、分隔符,甚至附加单击函数。请注意,您可以根据需要嵌套任意多个
    ul
    ,尽管切换确实有效,但它是无用的,因为单击打开子菜单将隐藏其父菜单。据我所知,如果您想在菜单中进行更深的嵌套,您需要创建自己的javascript处理程序或使用鼠标悬停自定义css


    不理解课程为什么重要。一个元素可以有许多类。此外,您还可以修改甚至不使用ui DropwDown中的CSS。我也遇到过类似的问题,并用这个方法解决了这个问题:它可以帮助您创建角度引导结构。当从服务中刷新时,我遇到了项目重复的问题,但这是一个新问题。我根据文档添加了适当的类,现在整个过程都不可见了。元素结构在DOM(firebug)中,但在导航结构中看不到任何类别。我添加了“ui.bootstrap”作为控制器模块的依赖项,并将ui-bootstrap-tpls-0.7.0.min.js添加到我的index.html页面,我还添加了bootstrap.css,甚至根据文档添加了额外的css行。有什么想法吗?Charlietfl,我创建了一个单独的Plunker项目,该项目只做了一些更改,将css类添加到必要的html中。好的,我看了你的演示。单击打开子菜单时,父菜单确实会关闭。似乎库应该为子菜单处理这个问题…@thebravedave是的,不幸的是,我几乎完全肯定它不是有意的。有一点需要考虑的是,嵌套的子菜单是一种糟糕的做法。在一个级别之后,这对用户来说是一种压力(我还要点击多少个呢?)。不过,你可以在这里轻松地创建自己的功能。当然,你最好也有一些悬停功能。
    *, *:before, *:after {
        -moz-box-sizing: border-box;
    }
    *, *:before, *:after {
        -moz-box-sizing: border-box;
    }
    .dropdown {
        position: relative;
    }
    .dropup, .dropdown {
        position: relative;
    }
    li {
        line-height: 20px;
    }
    *, *:before, *:after {
        -moz-box-sizing: border-box;
    }
    
    ...
    <li ng-repeat="child in parent.children" class="dropdown ng-scope">
                <recursive-list-item data-on-node-click="onNodeClickFn(node)" data-parent="child" class="ng-isolate-scope ng-scope">
                <a class="dropdown-toggle ng-scope ng-binding" href="javascript:void(0)">Kids Clothes</a>
    ...
    
    <nav>
      <div menu="menu"></div> <!-- the element here doesn't matter -->
    </nav>
    
    var app = angular.module('myApp', ['ui.bootstrap']);
    
    app.directive('menu', function() {
      return {
        restrict: 'A',
        scope: {
          menu: '=menu',
          cls: '=ngClass'
        },
        replace: true,
        template: '<ul><li ng-repeat="item in menu" menu-item="item"></li></ul>',
        link: function(scope, element, attrs) {
          element.addClass(attrs.class);
          element.addClass(scope.cls);
        }
      };
    });
    
    app.directive('menuItem', function($compile) {
      return {
        restrict: 'A',
        replace: true,
        scope: {
          item: '=menuItem'
        },
        template: '<li active-link><a href={{item.href}}>{{item.title}}</a></li>',
        link: function (scope, element, attrs) {
          if (scope.item.header) {
            element.addClass('nav-header');
            element.text(scope.item.header);
          }
          if (scope.item.divider) {
            element.addClass('divider');
            element.empty();
          }
          if (scope.item.submenu) {
            element.addClass('dropdown');
    
            var text = element.children('a').text();
            element.empty();
            var $a = $('<a class="dropdown-toggle">'+text+'</a>');
            element.append($a);
    
            var $submenu = $('<div menu="item.submenu" class="dropdown-menu"></div>');
            element.append($submenu);
          }
          if (scope.item.click) {
            element.find('a').attr('ng-click', 'item.click()');
          }
          $compile(element.contents())(scope);
        }
      };
    });
    
    app.controller('myCtrl', function($scope) {
      $scope.menu = [
        {
          "title": "Home",
          "href": "#"
        },
        {
          "title": "About",
          "href": "about"
        },
        {
          "title": "History",
          "href": "about/history"
        },
        {
          "title": "Contact",
          "href": "contact"
        },
        {
          "title": "Other things - in a list. (Click here)",
          "submenu": [
            {
              "header": "Sample Header"
            },
            {
              "title": "Some Link",
              "href": "some/place"
            },
            {
              "title": "Another Link",
              "href": "some/other/place"
            },
            {
              "divider": "true"
            },
            {
              "header": "Header 2"
            },
            {
              "title": "Again...a link.",
              "href": "errrr"
            },
            {
              "title": "Nest Parent",
              "submenu": [
                {
                  "title": "nested again",
                  "href": "nested/again"
                },
                {
                  "title": "me too",
                  "href": "sample/place"
                }
              ]
            }
          ]
        }
      ];
    });
    
    .dropdown-menu .dropdown-menu {
      margin: 0;
      left: 100%;
      top: -5px;
    }
    
    .dropdown-menu li:hover .dropdown-menu {
      display: block;
    }