mvc bootstrap sidebar add active class to the whole parents path - asp.net-mvc

I am building a sidebar navigation dynamically and I have the following issue:
Option 1 // add class active
Option 1.1 // add class active
Option 1.1.1 // add class active
Option 1.1.1.1 // add class active
option 1.1.1.1.1 // selected link id = 7 (this is guid in real app)
Option 1.1.2
Option 1.2
Option 2
Option 3
Basically the navigation is in the following format:
<ul>
<li>
link
</li>
<li>
link
<ul>
<li>
link
</li>
</ul>
</li>
</ul>
And here is what I try to do recursively.
#BuildNavigation(Model)
#helper BuildNavigation(IEnumerable<Menu> menu)
{
foreach (Menu item in menu)
{
<li>
#item.Title
#if (item.Items.Any())
{
<ul class="nav sub-menu">
#BuildNavigation(item.Items)
</ul>
}
</li>
}
}
This works fine, the sidebar is built. But how can I add the active classes to the <li> based on the current selection?
I can add a property to the Menu class bool IsActive and then within the view I can check if that menu is active but how can I add the active class to all parents <li> of that selected link?

Related

Build Menu from NavigableMap

In a Grails 3.3 application, I'm trying to create a menu configuration and I'd like to use application.groovy for that.
application.groovy:
mainmenuconfig {
menuitem_1 {
id = 'menuitem-1'
name='Home'
sub=null
}
menuitem_2 {
id ='menuitem-2'
name='Stammdaten'
sub = submenuitem_2 {
menuitem_2_1 {
id = 'menuitem-2-1'
name ='Stamm-A'
sub=null
}
}}
}
Retrieving the config via grailsApplication.config.get('mainmenuconfig') would give me the following:
[menuitem_1:[id:menuitem-1, name:Home, sub:null], menuitem_2:[id:menuitem-2, name:Stammdaten, submenuitem_2:[menuitem_2_1:[id:menuitem-2-1, name:Stamm-A]], sub:null]]
If I look at getClass() it says it's a org.grails.config.NavigableMap
Now, for my understanding, generating an <UL> ... <LI> tree should be done inside the View layer. For iterating through that structure, I will need recursion, because it can be n levels deep.
If I'm looking from main.gsp, I know the spot where I want to insert the menu tree, but how do I bring the data there and where do I do that recursion? Will I need a menu controller that is being called from the GSP? IMHO the GSP shouldn't do such calls. And on the other side, no controller should generate <UL> ... <LI> trees. I need the glue piece.
This sounds like a good use for an interceptor. You can have it add to your model after every action is finished. Then your view will have access to menu in its model and can build out the menu. It's fine to do recursion in your view if it's for display purposes.
class NavigationMenuInterceptor {
NavigationMenuInterceptor() {
matchAll()
}
boolean after() {
model.menu = grailsApplication.config.getProperty('mainmenuconfig', Map)
true
}
}
To render your menu, you can use a template that recursively renders itself. Depending on your desired HTML output it might be something like below.
In the main body:
<ul>
<g:each in="${menu}" var="menuitem">
<g:render template="menuitem" model="[menuitem: menuitem]"/>
</g:each>
</ul>
In your template _menuitem.gsp:
<li id="${menuitem.id}">
${menuitem.name}
</li>
<g:if test="${menuitem.sub}">
<li>
<ul>
<g:render template="menuitem" model="[menuitem: menuitem.sub]"/>
</ul>
</li>
</g:if>

MVC 5 #Html.ActionLink

I'm having some issues with some data filtering ; I want, from the following dropdown menu, to be able to display a list of projects by approval or not.
When the user creates a new project one of the fields is "approved", which is a boolean. That checkbox is left not checked and when the project has a Go the user picks that checkbox as an approved project.
Basically, I want, when the user picks the option "Approved", to be redirected to the list of already approved projects.
How can I do that?
<li class="dropdown">
Project Execution <span class="caret"></span>
<ul class="dropdown-menu">
<li> #Html.ActionLink("Approved", "Index", "NEWPROJECTs")</li>
<li role="separator" class="divider"></li>
<li>#Html.ActionLink("On Going", "Index", "NEWPROJECTs")</li>
<li role="separator" class="divider"></li>
<li>#Html.ActionLink("List", "Index", "PROJECTEXECUTIONs")</li>
</ul>
Using Route Parameters
If you have a single controller action that handles one or more of these operations, then you'll likely need to supply a route value to determine what data you should be filtering by:
public ActionResult NewProjects(string filter)
{
// Check the filter that was used and filter the content that you
// will pass to the view accordingly
// Get your projects prior to filtering
var projects = _context.Projects;
switch (filter)
{
case "ONGOING":
projects = projects.Where(p => p.Status == "ONGOING");
break;
default:
projects = projects.Where(p => p.Status == "APPROVED");
break;
}
return View(projects);
}
Then when you build your Action Links, simply specify the filter as a route value so that your controller action can consume it and properly filter your data:
<li>
#Html.ActionLink("Approved", "Index", "NEWPROJECTs", new { filter = "APPROVED"})
</li>
<li role="separator" class="divider"></li>
<li>
#Html.ActionLink("On Going", "Index", "NEWPROJECTs", new { filter = "ONGOING"})
</li>

Ajax loaded nested list Can't get event from inner

We have this nested list:
<ul id="AllTopics" data-role="listview" data-inset="true" data-filter="true" data-filter-placeholder="Search topic...">
<li>Polite Phrases<span class="ui-li-count">101</span>
<ul data-role="listview" data-inset="true" >
<li >Polite Phrases<span class="ui-li-count">101</span></li>
<li >At The End Of A Letter/Email<span class="ui-li-count">101</span></li>
</ul>
</li>
</ul>
The first <ul> with the id="AllTopics" is in the html documnet itself,
The inner <li><ul><li>... are loaded from Ajax call like:
on('pageinit'... event
... $("ul").append(...
I can get the event from the first new born <li> , like:
$('#AllTopics').on('click','li',function (event){...
But the inner <li> or <a> do not seem to fire events :-(
Ani ideas ?
Thank's in advance
The problem would be that the new content is loaded using an Ajax call, and you just setup the events before, so the new elements won't have them.
Try using delegate JQuery function:
$('#AllTopics').delegate('li a','click',function(){
alert('How you dare to click on my links?!');
});
EDIT
Other solution is to assign the events once elements are added via Ajax call.
// This is an example, retrieve the data on your own form
$.get('mypage.php',function(data){
// Add content to your DOM elements
$('#AllTopics').append(data);
// Assign events
$('#AllTopics').on('click','li',function (event){
alert('Holy moly, you keep clicking on my links!');
});
});
Note: I just realized that your HTML elements have this composition:
<ul>
<li>
<a/>
</li>
<span/>
<ul>
<li>
</a>
</li>
</ul>
</ul>
So, OF COURSE that is only affecting the first one because there are two levels of li - a (you have an ul element inside another one). You can define an ID for your second group of li - a elements to trigger events successfully or keep doing it in this way:
$('#AllTopics').delegate('li a','click',function(){
alert('How you dare to click on the first link?!');
});
$('#AllTopics').delegate('ul li a','click',function(){
alert('Stop clicking my children links!');
});

Active tag on MVC 4 layout page

I am using MVC 4 (Razor).
My HTML design contains a menu that (using some sort of javascript component),
I am looking for a smart way to mark the menu with what page am I currently on.
<li class="glyphicons home currentScroll active"><i></i><span>Dashboard</span></li>
<li class="glyphicons charts"> <i></i><span>Campaigns</span> </li>
<li class="glyphicons sort"> #Html.ActionLink("Home", "Index", "Home")</li>
<li class="glyphicons picture"> <li>#Html.ActionLink("Contact", "Contact", "Home")</li>
As you see the active li is marked, if I want to use this menu in the _layout.cshtml page, how can I change the Active mark according to the page I am currently loading?
Check this:
var controller = (string)ViewContext.RouteData.Values["controller"];
var action = (string)ViewContext.RouteData.Values["action"];
For each menu item check for equals menu controller and current controller (and action, may be)

Hide and visible the div tags of Layout.cshtml on the basis of user role in Asp.net MVC4(Razor)

I am having a master page which is having some menus for a Role called user and other menus are for the role of Admin, So what i am willing is to check the role of the user and and show some div tags and hide others on the basis of user role.
As, we don't have controller for layout.cshtml, so how i can set the viewModel for layout view
Wherein i can check the role of the current user
How to do role based checking on the layout.cshtml.
I have been through followin question but it has not been answered by now
How to Show or hide controls based on roles - ASP.NET MVC 4 Razor
So,Please tell me the possible solution and which way would be the best for applying role based checking in layout.cshtml
You could use the User.IsInRole method:
#if (User.IsInRole("admin"))
{
<li>Only the admin can see this menu item</li>
}
You can use Following code for role based checking
#if(Request.IsAuthenticated)
{
if(User.IsInRole("Admin")
{
<Ul Class="SubMenuItem">
<li> this menu item is for Admin role</li>
</Ul>
}
if(User.IsInRole("User")
{
<Ul Class="SubMenuItem">
<li> this menu item is for User role</li>
</Ul>
}
}
For unknown user
else
{
<Ul Class="SubMenuItem">
<li> this menu item is for Unknown user</li>
</Ul>
}

Resources