Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

active menu item - asp.net mvc3 master page

I've been scanning around trying to find an appropriate solution for assigning "active/current" class to menu items from the master page. The line is split down the middle with regards of whether to do this client vs server side.

Truthfully I'm new to both JavaScript and MVC so i don't have an opinion. I would prefer to do this in the "cleanest" and most appropriate way.

I have the following jQuery code to assign the "active" class to the <li> item...the only problem is the "index" or default view menu item will always be assigned the active class, because the URL is always a substring of the other menu links:

(default) index = localhost/ link 1 = localhost/home/link1 link 2 = localhost/home/link1  $(function () {  var str = location.href.toLowerCase();   $('#nav ul li a').each(function() {    if (str.indexOf(this.href.toLowerCase()) > -1) {     $(this).parent().attr("class","active"); //hightlight parent tab    } }); 

Is there a better way of doing this, guys? Would someone at least help me get the client-side version bulletproof? So that the "index" or default link is always "active"? Is there a way of assigning a fake extension to the index method? like instead of just the base URL it would be localhost/home/dashboard so that it wouldn't be a substring of every link?

Truthfully, i don't really follow the methods of doing this server-side, which is why I'm trying to do it client side with jQuery...any help would be appreciated.

like image 536
Michael Avatar asked Jan 18 '11 20:01

Michael


2 Answers

A custom HTML helper usually does the job fine:

public static MvcHtmlString MenuLink(     this HtmlHelper htmlHelper,      string linkText,      string actionName,      string controllerName ) {     string currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action");     string currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");     if (actionName == currentAction && controllerName == currentController)     {         return htmlHelper.ActionLink(             linkText,             actionName,             controllerName,             null,             new {                 @class = "current"             });     }     return htmlHelper.ActionLink(linkText, actionName, controllerName); } 

and in your master page:

<ul>     <li>@Html.MenuLink("Link 1", "link1", "Home")</li>     <li>@Html.MenuLink("Link 2", "link2", "Home")</li> </ul>  

Now all that's left is define the .current CSS class.

like image 122
Darin Dimitrov Avatar answered Oct 03 '22 22:10

Darin Dimitrov


Added support for areas:

public static class MenuExtensions {     public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper, string text, string action, string controller, string area = null)     {          var li = new TagBuilder("li");         var routeData = htmlHelper.ViewContext.RouteData;          var currentAction = routeData.GetRequiredString("action");         var currentController = routeData.GetRequiredString("controller");         var currentArea = routeData.DataTokens["area"] as string;          if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&             string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase) &&             string.Equals(currentArea, area, StringComparison.OrdinalIgnoreCase))         {             li.AddCssClass("active");         }         li.InnerHtml = htmlHelper.ActionLink(text, action, controller, new {area}, null).ToHtmlString();         return MvcHtmlString.Create(li.ToString());     } } 
like image 32
Ronnie Overby Avatar answered Oct 03 '22 22:10

Ronnie Overby