Reputation: 29
What I am trying to do is make an all purpose accordion-style navigation menu, with submenus, in AngularJS. It must dynamically load menu data, dynamically assign which menu items have submenus and which do not, and so forth - full list below.
I have tried with the angular-ui/bootstrap accordion elements but dont quite like how it allows me to handle their behaviour. It seems counterintuitive if I'm using <\accordion> and want to remove the accordion behaviour. I've resulted back to using list-items (<\li>) as it allows the most flexibility / styling.
What I want will do the following:
Based on this post here: Closing open submenu - jQuery accordion
I have a working version of this in jQuery - fiddle here: http://jsfiddle.net/52EH8/20/
function initMenu() {
$('#nav ul').hide();
$('#nav li a').click(
function () {
var checkElement = $(this).next();
if ((checkElement.is('ul')) && (checkElement.is(':visible'))) {
$('#nav ul:visible').slideToggle('normal');
}
if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
removeActiveClassFromAll();
$(this).addClass("active");
$('#nav ul:visible').slideToggle('normal');
checkElement.slideToggle('normal');
return false;
}
if($(this).siblings('ul').length==0 && $(this).parent().parent().attr('id')=='nav')
{
removeActiveClassFromAll();
$(this).addClass("active");
$('#nav ul:visible').slideToggle('normal');
return false;
}
});
}
function removeActiveClassFromAll() {
$('#nav li a').each(function (index) {
$(this).removeClass("active");
});
}
$(document).ready(function () {
initMenu();
});
$('#nav').click(function (e)
{
e.stopPropagation();
})
$(document).click(function () {
$('#nav').children('li').each(function () {
if ($(this).children('ul').css('display') == 'block') {
$(this).children('ul').slideToggle('normal')
$(this).children('a').removeClass('active')
}
})
})
My JSON menu (coffee-script) is:
S.mainMenu = [
name: 'Home'
url: 'home'
icon: 'fa-home'
,
name: 'Events'
url: 'events'
icon: 'fa-bullhorn'
,
name: 'Jobs'
url: 'jobs'
icon: 'fa-laptop'
,
name: 'Resources'
icon: 'fa-cloud-download'
submenu: [
name: 'Guides & Tutorials'
url: 'res-guides'
icon: 'fa-lightbulb-o'
,
name: 'Docs & Templates'
url: 'res-docs'
icon: 'fa-file-text'
,
name: 'Photos & Video'
url: 'res-media'
icon: 'fa-film'
]
,
name: 'TechGrind'
icon: 'fa-cogs'
submenu: [
name: 'Startup Hubs'
url: 'tg-hubs'
icon: ''
,
name: 'Membership'
url: 'tg-members'
icon: ''
,
name: 'Community'
url: 'tg-activities'
icon: ''
,
name: 'Incubator'
url: 'tg-incubator'
icon: ''
]
];
As you can see - there are 3 normal menus, and 2 menus-with-submenus.
More or less - how would one properly convert this from jQuery to "thinking Angular"?? ATM my main issue is: where to properly put $(document).ready to trigger initMenu()??
I have a strong feeling that this should all be placed into a directive instead, however - or 2 directives (1=top-level accordion menu, 2=submenu). I am not that good with directives yet though so this is my problem.
I have seen many many posts about this type of menu - it would be beneficial to allot of people I think to make one that is generic, dynamically loaded, with X number of menus, Y number of submenus, and so forth. I've formatted my question ACCORDINgly (pun intended) so that it can hopefully serve all needs.
Thanks in advance!
Upvotes: 2
Views: 15997
Reputation: 52867
Here is an angular directive that is based on bootstrap's collapse plugin. It uses zero jQuery and you can customize it further if you want.
The accordion behavior relies on the following template from Bootstrap:
<div id="parent">
<div class="panel">
<div data-toggle="collapse" data-parent="#parent" data-target="#child">test</div>
<div id="child" class="collapse in">
This is the content
</div>
</div>
<div class="panel">
<div data-toggle="collapse" data-parent="#parent" data-target="#child2">test</div>
<div id="child2" class="collapse">
This is the content
</div>
</div>
</div>
Upvotes: 1
Reputation: 5865
If you are already using Bootstrap for styling I highly recommend to use Angular-UI Bootstrap. Using this module you don't have to reinvent the wheel. Just take a look at this example, which is based on the Accordion example in the documentation.
Upvotes: 1