0

I'm trying to create a toggle effect on the navagation tabs in an MVC 5/Razor 3 application, with bootstrap css. My current shared _layout

        <div class="navbar-collapse collapse"> 
            <ul class="nav nav-pills">                           
                <li>@Html.ActionLink("Applications", "Index", "SecureApps")</li>
                <li>@Html.ActionLink("Users", "Index", "Users")</li>
                <li>@Html.ActionLink("BU Groups", "Index", "BUGroups")</li>
                <li>@Html.ActionLink("Logs", "Index", "AppLogs")</li> 
            </ul>         
        </div>

I want to be able to highlight the tabs like this Demo when a tab is clicked and I'm on an active page.

I've found a solution Here and updated my code to this

                <li class="active">@Html.ActionLink("Applications", "Index", "SecureApps", null, new { id = "menu_text", data_toggle = "tab" }))</li>
                <li>@Html.ActionLink("Users", "Index", "Users", null, new { id = "menu_text", data_toggle = "tab" })</li>
                <li>@Html.ActionLink("BU Groups", "Index", "BUGroups", null, new { id = "menu_text", data_toggle = "tab" }))</li>
                <li>@Html.ActionLink("Logs", "Index", "AppLogs", null, new { id = "menu_text", data_toggle = "tab" }))</li>

Hovering over each tab shows the correct URL route. however, I'm getting a jQuery javascript runtime error

Unhandled exception at line 1864, column 2 in http://localhost:19932/Scripts/jquery-1.10.2.js 0x800a139e - JavaScript runtime error: Syntax error, unrecognized expression: /Users

this is the code it points to in the js library

Sizzle.error = function( msg ) {
throw new Error( "Syntax error, unrecognized expression: " + msg );};

putting a breakpoint on the @model declaration on the destination Index pages doesn't even get hit.

Community
  • 1
  • 1
stevenjmyu
  • 926
  • 4
  • 16
  • 31

1 Answers1

2

Client-side vs Server-side

One of the issues here is that when your links are clicked, they are actually going to navigate to the appropriate Controller Action as expected. When this occurs, your current client-side code such as your selection, will be completely forgotten (as the page will be refreshed).

Client-side changes are generally always going to be "wiped-away" whenever the page is refreshed, so you'll need a way to persist these at the server-level.

Store at the Server-Level

You may want to consider handling this using some type of server-side variable to determine "where you are" within the application and setting the "active" class on your appropriate <li> element for your tabs. There are a variety of ways you could handle this, setting a ViewBag property within your Controller Action, populating a value on your Model to indicate the current area, etc.

Since your links each point to different Controllers, you could even determine which one to use based off of the current Controller as seen below :

<!-- Use your Controller to determine where you are -->
@{ var controller = ViewContext.RouteData.Values["controller"]; }
<div class="navbar-collapse collapse"> 
        <ul class="nav nav-pills">                           
            <li @(controller == "SecureApps" ? "class=active" :"")>@Html.ActionLink("Applications", "Index", "SecureApps")</li>
            <li @(controller == "Users" ? "class=active" :"")>@Html.ActionLink("Users", "Index", "Users")</li>
            <li @(controller == "BUGroups" ? "class=active" :"")>@Html.ActionLink("BU Groups", "Index", "BUGroups")</li>
            <li @(controller == "AppLogs" ? "class=active" :"")>@Html.ActionLink("Logs", "Index", "AppLogs")</li> 
        </ul>         
</div>

Or... just use more jQuery

Since your ActionLinks are going to resolve to specific URLs for your actions, you could conceivably just use a bit of jQuery to find any links that pointed to the current location and make those active :

$(function(){
     // Find an element that points to the current URL and make it active
     $('a[href="@Url.Action(Convert.ToString(ViewContext.RouteData.Values["action"]), Convert.ToString(ViewContext.RouteData.Values["controller"]))"]').closest('li').addClass('active');
});

The Url.Action() method will take in the current controller and action, rendering it's target location and it will find any links that point to the same value and set those as "active".

Rion Williams
  • 74,820
  • 37
  • 200
  • 327