web-dev-qa-db-fra.com

élément de menu actif - page principale asp.net mvc3

J'ai parcouru autour d'essayer de trouver une solution appropriée pour attribuer la classe "active/actuelle" aux éléments de menu de la page maître. La ligne est divisée au milieu en ce qui concerne l'opportunité de faire cela côté client vs serveur.

En vérité, je suis nouveau sur JavaScript et MVC, donc je n'ai pas d'opinion. Je préférerais le faire de la manière "la plus propre" et la plus appropriée.

J'ai le code jQuery suivant pour affecter la classe "active" à l'élément <li> ... le seul problème est que l'élément de menu "index" ou la vue par défaut sera toujours affecté à la classe active, car l'URL est toujours une sous-chaîne des autres liens du 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
   }
});

Y a-t-il une meilleure façon de le faire, les gars? Quelqu'un pourrait-il au moins m'aider à obtenir la version côté client à l'épreuve des balles? Pour que "l'index" ou le lien par défaut soit toujours "actif"? Existe-t-il un moyen d'attribuer une fausse extension à la méthode d'index? comme au lieu de l'URL de base, ce serait localhost/home/dashboard pour que ce ne soit pas une sous-chaîne de chaque lien?

À vrai dire, je ne suis pas vraiment les méthodes de ce côté serveur, c'est pourquoi j'essaie de le faire côté client avec jQuery ... toute aide serait appréciée.

65
Michael

Un assistant HTML personnalisé fait généralement l'affaire:

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

et dans votre page maître:

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

Il ne reste plus qu'à définir la classe CSS .current.

114
Darin Dimitrov

Ajout de la prise en charge des zones:

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

Voici ma solution à ce problème.

J'ai créé la méthode d'extension suivante de la classe 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";
    }

Ensuite, j'ai mon menublock. Cela ressemble à ceci:

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

Ma méthode renvoie donc le nom de classe à chaque div en fonction de l'action actuelle du contrôleur Home. Vous pouvez aller plus loin et ajouter à la méthode un paramètre, qui spécifie le nom du contrôleur pour éviter les problèmes, lorsque vous avez des actions avec le même nom mais de contrôleurs différents.

4
Tim Gim

Grâce à JQuery, vous pouvez faire comme ceci:

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

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

2
oyaebunterkrah