I'm working with an asp.net mvc4 and Angular JS (started from John Papa's HotTowel.angular.Breeze SPA). I have added a dropdown menu to the sidebar.html, and have also added the appropriate routes to config.route.js.
I find the tricky part is to properly wire-up the dropdown menus to the Angular routes.
This setup is mostly working, except that when I click on the "MR Reports" dropdown menu below, it's right-away firing a route (i.e. when I hover over MR Reports, it shows the link "localhost:49479/index.html#". In other words, the "MR Reports" should be a dropdown menu and NOT trigger a route change until I choose a dropdown menu item.
I'm not sure if the change should be in config.route.js or in the sidebar.html code.
UPDATE:
I'm assuming I can use the Angular ngHref directive, something like ng-href="#{{r.url}}"
, to dynamically exclude the top-level href tag if there's a sub menu.
Perhaps I can use ng-if="r.config.sub"
as a guide as well.
Here is the contents of config.route.js (please note the "sub:" section for the sub-menus):
(function () {
'use strict';
var app = angular.module('app');
// Collect the routes
app.constant('routes', getRoutes());
// Configure the routes and route resolvers
app.config(['$routeProvider', 'routes', routeConfigurator]);
function routeConfigurator($routeProvider, routes) {
routes.forEach(function (r) {
$routeProvider.when(r.url, r.config);
});
$routeProvider.otherwise({ redirectTo: '/' });
}
// Define the routes
function getRoutes() {
return [
{
url: '/',
config: {
templateUrl: 'app/dashboard/dashboard.html',
title: 'dashboard',
settings: {
nav: 1,
content: '<i class="fa fa-dashboard"></i> Dashboard'
}
}
}, {
url: '/admin',
config: {
title: 'admin',
templateUrl: 'app/admin/admin.html',
settings: {
nav: 2,
content: '<i class="fa fa-lock"></i> Admin'
}
}
},
{
url: '/testgrid',
config: {
title: 'grids',
templateUrl: 'app/testgrid/testgrid.html',
settings: {
nav: 3,
content: '<i class="fa fa-globe"></i> TestGrid'
}
}
},
{
config: {
title: 'reports',
templateUrl: 'app/testgrid/testgrid.html',
settings: {
nav: 4,
content: '<i class="fa fa-plus-square "></i> MR Reports <b class="caret"></b>'
},
sub: [
{
url: '/testgrid',
title: 'reports1',
templateUrl: 'app/testgrid/testgrid.html',
settings: {
content: 'TestGrid'
}
},
{
url: '/admin',
title: 'Admin2',
templateUrl: 'app/admin/admin.html',
settings: {
content: 'Admin2'
}
}
]
},
}
];
}
})();
and my sidebar.html is defined as :
<div data-cc-sidebar data-ng-controller="sidebar as vm">
<div class="sidebar-filler"></div>
<div class="sidebar-dropdown"><a href="#">Menu</a></div>
<div class="sidebar-inner">
<div class="sidebar-widget">
</div>
<ul class="navi">
<li class="nlightblue fade-selection-animation"
ng-class="{dropdown: r.config.sub}"
data-ng-repeat="r in vm.navRoutes">
<a href="#{{r.url}}" data-ng-bind-html="r.config.settings.content" ng-class="{'dropdown-toggle': r.config.sub}" data-ng-class="vm.isCurrent(r)" data-toggle="dropdown" ></a>
<ul ng-if="r.config.sub" class="dropdown-menu">
<li ng-repeat="submenu in r.config.sub">
<a href="#{{submenu.url}}" data-ng-bind-html="submenu.settings.content"></a>
</li>
</ul>
</li>
</ul>
</div>
I'm not crazy about my hack, but it ended up working. I used one ng-if
to render the href link for non-dropdown menu items, and another ng-if
to EXCLUDE the href tag for the dropdowns.
And in the getRoutes() function, I EXCLUDE the url:
property at the top-level of the dropdown.
<ul class="navi">
<li class="nlightblue fade-selection-animation"
ng-class="{dropdown: r.config.sub}"
data-ng-repeat="r in vm.navRoutes">
<a ng-if="r.url" href="#{{r.url}}" data-ng-bind-html="r.config.settings.content"
ng-class="{'dropdown-toggle': r.config.sub}"
data-ng-class="vm.isCurrent(r)"
data-toggle="dropdown" ></a>
<a ng-if="r.config.sub" data-ng-bind-html="r.config.settings.content"
ng-class="{'dropdown-toggle': r.config.sub}"
data-ng-class="vm.isCurrent(r)"
data-toggle="dropdown" ></a>
<ul ng-if="r.config.sub" class="dropdown-menu">
<li ng-repeat="submenu in r.config.sub">
<a href="#{{submenu.url}}" data-ng-bind-html="submenu.settings.content"></a>
</li>
</ul>
</li>
config.route.js function:
function getRoutes() {
return [
{
url: '/',
config: {
templateUrl: 'app/dashboard/dashboard.html',
title: 'dashboard',
settings: {
nav: 1,
content: '<i class="fa fa-dashboard"></i> Dashboard'
}
}
}, {
url: '/admin',
config: {
title: 'admin',
templateUrl: 'app/admin/admin.html',
settings: {
nav: 2,
content: '<i class="fa fa-lock"></i> Admin'
}
}
},
{
url: '/testgrid',
config: {
title: 'grids',
templateUrl: 'app/testgrid/testgrid.html',
settings: {
nav: 3,
content: '<i class="fa fa-globe"></i> TestGrid'
}
}
},
{ // Exclude url: at this top level
config: {
title: 'reports',
settings: {
nav: 4,
content: '<i class="fa fa-plus-square "></i> MR Reports <b class="caret"></b>'
},
sub: [
{
url: '/testgrid',
title: 'reports1',
templateUrl: 'app/testgrid/testgrid.html',
settings: {
content: 'TestGrid'
}
},
{
url: '/admin',
title: 'Admin2',
templateUrl: 'app/admin/admin.html',
settings: {
content: 'Admin2'
}
}
]
},
}
];
}