2011-01-18 7 views
64

Szukałem w pobliżu, próbując znaleźć odpowiednie rozwiązanie do przypisywania klasy "aktywny/aktualny" do elementów menu ze strony wzorcowej. Linia jest podzielona w dół w odniesieniu do tego, czy wykonać tę stronę kontra klient.aktywny element menu - asp.net strona główna mvc3

Prawdę mówiąc, jestem nowy zarówno w JavaScript, jak i MVC, więc nie mam zdania. Wolałbym robić to w "najczystszy" i najbardziej odpowiedni sposób.

Mam następujący kod jQuery, aby przypisać "aktywną" klasę do pozycji <li> ... jedynym problemem jest "indeks" lub domyślny element menu widoku zawsze będzie przypisany do aktywnej klasy, ponieważ adres URL jest zawsze podciągiem innych linków menu:

(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 
    } 
}); 

Czy jest lepszy sposób na robienie tego, chłopaki? Czy ktoś przynajmniej pomógłby mi uzyskać wersję kuloodporną po stronie klienta? Aby "indeks" lub domyślny link był zawsze "aktywny"? Czy istnieje sposób przypisania fałszywego rozszerzenia do metody indeksu? jak zamiast podstawowego adresu URL byłby to localhost/home/dashboard, aby nie był podłańcuchem każdego linku?

Prawdę mówiąc, nie podążam za metodami działania po stronie serwera, dlatego próbuję zrobić to po stronie klienta z jQuery ... każda pomoc byłaby doceniana.

Odpowiedz

114

pomocnik zwyczaj HTML zazwyczaj robi to praca dobrze:

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); 
} 

i na stronie głównej:

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

Teraz pozostało tylko zdefiniowanie klasy .current CSS.

+27

Warto zauważyć, że htmlHelper.ActionLink() wymaga "używania System.Web.Mvc.Html;" – 4imble

+1

Działa doskonale +1 – 4imble

+5

Musisz również zaimportować przestrzeń nazw w swoim widoku, jeśli używasz Razor w MVC3, możesz to zrobić, po prostu dodając @using do widoku – Duncan

-1

Zazwyczaj przypisuję klasę do znacznika body, który jest oparty na częściach ścieżki. Tak więc, jeśli robisz String.Replace na ścieżce do turn/blogs/posts/1 to class = "blogs posts 1".

Następnie można przypisać reguły CSS do obsługi tego. Na przykład, jeśli masz menu dla „blogów”, można po prostu zrobić regułę jak

BODY.blogs li.blogs { /* your style */} 

lub jeśli chcesz konkretny styl jeśli na stanowisku wice tylko jeśli jesteś w katalogu głównym blogu strona

BODY.blogs.posts li.blogs {/* your style */} 
+1

nie szaleję tego rozwiązania ... wymaga utworzenia klasy dla każdy pojedynczy element menu, prawda? – Michael

4

Oto moje rozwiązanie tego problemu.

I stworzył następującą metodę rozszerzenia klasy HtmlHelpers:

public static class HtmlHelpers 
{ 
    public static string SetMenuItemClass(this HtmlHelper helper, string actionName) 
    { 
     if (actionName == helper.ViewContext.RouteData.Values["action"].ToString()) 
      return "menu_on"; 
     else 
      return "menu_off"; 
    } 

Następnie Mam menublock. Wygląda to tak:

<div id="MenuBlock"> 
    <div class="@Html.SetMenuItemClass("About")"> 
     <a>@Html.ActionLink("About", "About", "Home")</a></div> 
    <img height="31" width="2" class="line" alt="|" src="@Url.Content("~/Content/theme/images/menu_line.gif")"/> 
    <div class="@Html.SetMenuItemClass("Prices")"> 
     <a>@Html.ActionLink("Prices", "Prices", "Home")</a></div> 
</div> 

Tak więc moja metoda zwraca nazwę klasy do każdego elementu div zgodnie z bieżącą akcją kontrolera głównego. Możesz wejść głębiej i dodać do metody jeden parametr, który określa nazwę kontrolera, aby uniknąć problemów, gdy masz akcje o tej samej nazwie, ale o różnych kontrolerach.

5

Dodano wsparcie dla obszarów:

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()); 
    } 
} 
2

Poprzez JQuery u można zrobić tak:

$(document).ready(function() { 
    highlightActiveMenuItem(); 
}); 

highlightActiveMenuItem = function() { 
    var url = window.location.pathname; 
    $('.menu a[href="' + url + '"]').addClass('active_menu_item'); 
}; 

.active_menu_item { 
    color: #000 !important; 
    font-weight: bold !important; 
} 

oryginalny: http://www.paulund.co.uk/use-jquery-to-highlight-active-menu-item