Активный пункт меню - главная страница asp.net mvc3

Я просматривал, пытаясь найти подходящее решение для назначения класса "активный/текущий" элементам меню на главной странице. Линия разделяется на середину относительно того, следует ли делать этот клиент на стороне сервера.

Честно говоря, я новичок в JavaScript и MVC, поэтому у меня нет мнения. Я бы предпочел сделать это "самым чистым" и наиболее подходящим способом.

У меня есть следующий код jQuery, чтобы назначить "активный" класс <li> item... единственная проблема заключается в том, что элемент меню "индекс" или элемент по умолчанию всегда будет присвоен активному классу, потому что URL-адрес всегда является подстрокой других ссылок меню:

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

Есть ли лучший способ сделать это, ребята? Кто-нибудь хотя бы поможет мне получить версию на стороне клиента? Так что "индекс" или ссылка по умолчанию всегда "активны"? Есть ли способ назначить поддельное расширение методу индекса? а не только базовый URL-адрес, он будет localhost/home/dashboard, чтобы он не был подстрокой каждой ссылки?

Честно говоря, я действительно не придерживаюсь методов выполнения этой серверной части, поэтому я пытаюсь сделать это на стороне клиента с помощью jQuery... любая помощь будет оценена по достоинству.

Ответ 1

Пользовательский помощник HTML обычно отлично выполняет работу:

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

и на главной странице:

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

Теперь все, что осталось, определяют класс .current CSS.

Ответ 2

Добавлена ​​поддержка областей:

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

Ответ 3

Вот мое решение этой проблемы.

Я создал следующий метод расширения класса 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";
    }

Тогда у меня есть мой menublock. Это выглядит так:

<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>

Таким образом, мой метод возвращает имя класса для каждого div в соответствии с текущим действием контроллера Home. Вы можете пойти глубже и добавить к методу один параметр, который задает имя контроллера, чтобы избежать проблем, когда у вас есть действия с тем же именем, но с разными контроллерами.

Ответ 4

Через JQuery u можно сделать следующее:

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

Оригинал: http://www.paulund.co.uk/use-jquery-to-highlight-active-menu-item

Ответ 5

Обычно я назначаю класс тегу body, который основывается на частях пути. Так что, если вы делаете String.Replace на пути, чтобы включить /blogs/posts/ 1 в class= "blogs posts 1".

Затем вы можете назначить правила CSS для этого. Например, если у вас есть пункт меню для "блогов", вы можете просто сделать правило вроде

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

или если вам нужен конкретный стиль, если ваш на пост только тик, если вы находитесь на корневой странице блога

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