Многоуровневое раскрывающееся меню AngularJS для структуры меню, созданной из рекурсивной директивы
У меня есть слабый рассол здесь. Я должен получить свое многоуровневое навигационное меню от вызова веб-службы.
Поскольку в моем меню навигации может быть бесконечное количество подменю, мне пришлось использовать рекурсивную директиву для построения структуры навигации родитель / потомок. Сейчас я пытаюсь понять, как превратить его в функциональную структуру дропменю. Я взглянул на angularui-bootstrap, и у них есть Dropdown Toggle, который имеет некоторые базовые функциональные возможности dropmenu, но так как я использовал рекурсивную директиву, моя структура меню уже имеет сгенерированные angularjs классы css. В выпадающих меню angularjs-bootstrap есть классы 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 > 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>
Это был пример HTML, который генерируется как окончательный вывод для моего рекурсивного меню навигации. Если он настроен таким образом, все подменю ng-click активны и имеют ту же область видимости, что и основной контроллер (все денди, за исключением того, что оно не похоже на выпадающее меню)
Вот пример структуры dropmenu для angularjs-bootstrap
<li class="dropdown" ng-controller="DropdownCtrl">
<a class="dropdown-toggle">
Click me for a dropdown, yo!
</a>
<ul class="dropdown-menu">
<li ng-repeat="choice in items">
<a>{{choice}}</a>
</li>
</ul>
</li>
У него очень отличная структура класса CSS, чем у меня, так что "выпадающий" angularjs-bootstrap не будет работать с моим.
У кого-нибудь есть предложения для меня? Имейте в виду, что, поскольку я получаю свою структуру навигации через json через вызов веб-службы, я должен использовать рекурсивные angularjs для создания структуры родительского / дочернего меню.
Если кто-то запутается в моей html директиве, сгенерированной здесь, я могу показать свой собственный код директивы, но пока не попросит краткости. Мой пользовательский код директивы работает только для построения структуры навигации и сохраняет все области директив, связанные с областью действия основного контроллера (т. Е. Активным нажатием), но он не имеет стиля / прокрутки активен.
***** ОБНОВЛЕНИЕ ******** Я создал репликацию плунжера, которая почти такая же. В моем проекте я получал данные своего меню навигации из службы angularjs, которая выполняла бы вызов веб-службы для остальных веб-служб на моем сервере, но у меня этого нет, поэтому я просто вручную создал json для каждого из моих сервисы, которые делают вызовы REST webservice. Важной частью является рекурсивная директива. Справа внизу вы найдете ссылку на проект plunker. Кто-нибудь может мне помочь?
Проект Плункер ------------------------------------------------ -------------
************* НОВОЕ ОБНОВЛЕНИЕ ***************** Комментарий от Charlietfl о том, что я могу иметь несколько классов css в моей структуре выпадающего меню навигации. Я пытаюсь сделать это с помощью angularui-bootstrap. Я следовал инструкциям по добавлению этого в свой проект и создал новый проект Plunker, основанный на старом проекте plunker, но с дополнительными классами dropmenu css, добавленными в структуру навигации. Вот проект Плункер: Проект Плункер
Элементы навигации по-прежнему отображаются в DOM, но они не видны. Я посмотрел на CSS для первого элемента ul, и это так:
*, *:before, *:after {
-moz-box-sizing: border-box;
}
*, *:before, *:after {
-moz-box-sizing: border-box;
}
.dropdown-menu {
background-clip: padding-box;
background-color: #FFFFFF;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 4px;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.176);
display: none;
float: left;
font-size: 14px;
left: 0;
list-style: none outside none;
margin: 2px 0 0;
min-width: 160px;
padding: 5px 0;
position: absolute;
top: 100%;
z-index: 1000;
}
Он был получен из официального файла начальной загрузки css. Не уверен точно, почему это не видно. Не уверен, что это поможет, но вот CSS для следующего элемента li после ul
*, *: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;
}
Имейте в виду, что вам нужно перейти на страницу plunker, чтобы увидеть обновленный код, начиная с того момента, когда я добавил теги css, необходимые для angularui-bootstrap. Чтобы увидеть невидимые элементы навигации, вам понадобится что-то вроде Firebug, чтобы увидеть DOM.
Вот пример некоторого окончательного вывода html (из DOM) из моего обновления, чтобы попытаться поработать с классами angularui-bootstrap 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-bootstrap не работает, заключается в том, что элемент "recursive-list-item.." является дочерним элементом элемента "li" и родительским элементом для элемента "a". Правильно ли это мое предположение?
1 ответ
Это то, что я использую, и у него много дополнительных функций, которые довольно приятны. Смотрите использование $scope.menu
и что происходит, когда вы раскрываете раскрывающийся список - вы можете добавлять заголовки, разделители и даже прикреплять функции щелчка. Обратите внимание, что вы можете вложить как можно больше ul
как вы хотите, и хотя переключение работает, оно бесполезно, так как нажатие, чтобы открыть подменю, скроет его родителя. Насколько я знаю, вам нужно было бы создать свой собственный обработчик javascript или пользовательский css, используя hovers, если вы хотите более глубокое вложение в меню.
<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;
}