I have seen several examples on creating a HTML helper method for active
menu items.
**Summary:**
Simply put, in an MVC project, using the Twitter Bootstrap, I am trying to preserve the open state of a collapsible menu when a child is selected.
I am using a collapsible menu, where the parent's css (the selected item) needs to include active open
if a child is selected. This will ensure that the menu is open at the right location. With the use of another HTML helper, the active item is already set to active
.
HTML for the menu:
<div id="sidebar">
<ul>
<li class="active"><a href="dashboard.html"><i class="icon-home"></i> <span>Dashboard</span></a></li>
<li class="submenu">
<a href="#"><i class="icon-beaker"></i> <span>UI Lab</span> <i class="arrow icon-chevron-right"></i></a>
<ul>
<li><a href="interface.html">Interface Elements</a></li>
<li><a href="jquery-ui.html">jQuery UI</a></li>
<li><a href="buttons.html">Buttons & icons</a></li>
</ul>
</li>
<li class="submenu">
<a href="#"><i class="icon-th-list"></i> <span>Form elements</span> <i class="arrow icon-chevron-right"></i></a>
<ul>
<li><a href="form-common.html">Common elements</a></li>
<li><a href="form-validation.html">Validation</a></li>
<li><a href="form-wizard.html">Wizard</a></li>
</ul>
</li>
<li><a href="tables.html"><i class="icon-th"></i> <span>Tables</span></a></li>
<li><a href="grid.html"><i class="icon-th-list"></i> <span>Grid Layout</span></a></li>
<li class="submenu">
<a href="#"><i class="icon-file"></i> <span>Sample pages</span> <i class="arrow icon-chevron-right"></i></a>
<ul>
<li><a href="invoice.html">Invoice</a></li>
<li><a href="chat.html">Support chat</a></li>
<li><a href="calendar.html">Calendar</a></li>
<li><a href="gallery.html">Gallery</a></li>
<li><a href="messages.html">Messages</a></li>
</ul>
</li>
<li>
<a href="charts.html"><i class="icon-signal"></i> <span>Charts & graphs</span></a>
</li>
<li>
<a href="widgets.html"><i class="icon-inbox"></i> <span>Widgets</span></a>
</li>
</ul>
</div>
Here is the helper method for items:
public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper,
string text,
string action,
string controller,
string iconClass)
{
var li = new TagBuilder("li");
var routeData = htmlHelper.ViewContext.RouteData;
var currentAction = routeData.GetRequiredString("action");
var currentController = routeData.GetRequiredString("controller");
if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
{
li.AddCssClass("active");
}
var i = new TagBuilder("i");
i.AddCssClass(iconClass);
var basePath = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
//li.InnerHtml = htmlHelper.ActionLink("<i>something</i>" + text, action, controller).ToHtmlString();
li.InnerHtml = htmlHelper.Raw(string.Format("<a href=\"{0}/{1}/{2}\"><i class=\"{4}\"></i>{3}</a>", basePath, controller, action, text, iconClass)).ToString();
return MvcHtmlString.Create(li.ToString());
}
And implemented like this:
<div id="sidebar">
<ul>
@Html.MenuItem("Dashboard", "Index", "Dashboard", "icon-home")
@* <li class="active"><a href="dashboard.html"><i class="icon-home"></i> <span>Dashboard</span></a></li>*@
<li class="submenu">
<a href="#"><i class="icon-beaker"></i> <span>UI Lab</span> <i class="arrow icon-chevron-right"></i></a>
<ul>
<li>@Html.MenuItem("Websites", "Index", "Websites", null)</li>
<li><a href="jquery-ui.html">jQuery UI</a></li>
<li><a href="buttons.html">Buttons & icons</a></li>
</ul>
</li>
<li class="submenu">
<a href="#"><i class="icon-th-list"></i> <span>Form elements</span> <i class="arrow icon-chevron-right"></i></a>
<ul>
<li><a href="form-common.html">Common elements</a></li>
<li><a href="form-validation.html">Validation</a></li>
<li><a href="form-wizard.html">Wizard</a></li>
</ul>
</li>
So what I don't have is something for the submenu items.
Is there a simpler way of trying to accomplish this?
--UPDATE--
I'm guessing that putting this into a partial view may be best. I need to find some way to preserve the selected item on click to reference it on every menu item, rather than check if the controller/action matches in order to set the current item to "active". A controller method that activates on click, checks if the currently selected item is a parent or child, and if the parent matches a child, then format differently? I'm sure there has to be an easier way.