Aller au contenu

Définition du lien actif dans une page Razor

·456 mots·3 mins
Sommaire

Un élément essentiel pour la compréhension de l’interface par l’utilisateur est de savoir où il se trouve. Pour cela, il existe plusieurs patterns (breadcrumb, historique de navigation, …): tout pour que l’utilisateur comprenne rapidement et en un coup d’oeil l’emplacement où il se trouve et son contexte.

Un élément à combiner avec les idées ci-dessous est de placer le lien actif de la page en gras, afin d’avoir une bonne visualisation de “où suis-je?”.

L’implémentation la plus simple consiste à comparer le contexte de la requête avec la page qui a été/est en cours de génération. Et plutôt que d’effectuer ces vérifications directement dans le template de la page, nous pouvons définir un helper, qui nous permettra de générer dynamiquement un élément <li> auquel sera associée la classe CSS active s’il correspond à l’URL actuelle du navigateur.

Les paramètres nécessaires à la génération du tag HTML sont:

  1. Une méthode d’extension, pour que cela s’applique à n’importe quel instance de type HtmlHelper
  2. Le texte qui sera affiché dans notre élément
  3. L’action et le contrôler (au sens MVC)
  4. Les routes
  5. D’éventuels attributs HTML

Tout ceci nous permettra d’appeler directement notre helper de la manière suivante:

@Html.MenuItem("Details", "Details", "Node", new { id = Model.ID }, null)

En pratique
#

using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace RPS.Web.Helpers
{
    public static class MenuExtensions
    {
        public static MvcHtmlString MenuItem(
            this HtmlHelper htmlHelper,
            string text,
            string action,
            string controller,
            object routeValues,
            object htmlAttributes
        )
        {
            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");
            }

            li.InnerHtml = htmlHelper.ActionLink(
                text,
                action,
                controller,
                routeValues,
                htmlAttributes
            ).ToHtmlString();

            return MvcHtmlString.Create(li.ToString());
        }
    }
}

Dernier problème: cette extension de méthode ne peut être appelée directement depuis la syntaxe Razor. Pour pallier à cela, il suffit d’ajouter le namespace défini ci-dessus dans le fichier Web.config qui se trouve dans le répertoire Views:

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <!-- On ajoute la référence vers le namespace à utiliser -->
        <add namespace="MyProject.Web.Helpers" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

On peut ensuite l’appeler directement dans le rendu HTML de la page (pas besoin de définir l’élément li, puisque celui-ci sera généré par le helper):

<ul id="entityLinksMenu">
	@Html.MenuItem("Details", "Details", "Node", new { id = Model.ID }, null)
	@Html.MenuItem("Display", "Display", "Node", new { id = Model.ID }, null)
</ul>

Et finalement, on ajoute une classe .active dans le style CSS, qui mettra le texte en gras:

#nodeLinksMenu li.active {
	font-weight: bold;
}

Références
#