web-dev-qa-db-fra.com

MVC avec Bootstrap Navbar - Définir l'élément sélectionné sur actif

J'apprends Bootstrap et je ne peux pas mettre l'élément sélectionné dans un état "actif". L'état actif reste sur l'élément par défaut. L'élément nouvellement sélectionné/cliqué devient brièvement actif, mais revient en arrière. J'ai lu tous les articles et je ne parviens toujours pas à faire fonctionner ce code. J'utilise MVC5 et JQuery 2.1.

EDIT: Si je change les hrefs de li en href = "#", la classe active sera appliquée correctement. Que se passe-t-il quand une nouvelle vue est chargée? Je pense que la réponse de Sebastian est proche, mais elle devient compliquée avec Areas. 

Balisage

<div class="navbar-wrapper">
    <div class="container">
        <div class="navbar navbar-inverse navbar-fixed-top">

            <div class="navbar-header">
                <a class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </a>
                <a class="navbar-brand" href="#">Test</a>
            </div>
            <div class="btn-group pull-right">
                <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
                    <i class="icon-user"></i>Login
          <span class="caret"></span>
                </a>
                <ul class="dropdown-menu">
                    <li><a href="#">Profile</a></li>
                    <li class="divider"></li>
                    <li><a href="#">Sign Out</a></li>
                </ul>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="~/Home">Home</a></li>
                    <li><a href="~/Home/About">About</a></li>
                    <li><a href="~/Student">Students Sample</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            <li><a href="~/Admin/Home/Index"">Admin</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                            <li><a href="#">One more separated link</a></li>
                        </ul>
                    </li>
                </ul>
            </div>

        </div>
    </div>
    <!-- /container -->
</div>
<!-- /navbar wrapper -->

Script

<script type="text/javascript">

    $(function () {
        $('.navbar-nav li').click(function () {
            $(this).addClass('active').siblings().removeClass('active');
        });
    });

</script>

EDIT: Voici ce que j'ai fini par faire avec l'aide des réponses postées et des recherches.

public static string MakeActive(this UrlHelper urlHelper,string action, string controller, string area = "")
        {
            string result = "active";
            string requestContextRoute;
            string passedInRoute;

            // Get the route values from the request           
            var sb = new StringBuilder().Append(urlHelper.RequestContext.RouteData.DataTokens["area"]);
            sb.Append("/");
            sb.Append(urlHelper.RequestContext.RouteData.Values["controller"].ToString());
            sb.Append("/");
            sb.Append(urlHelper.RequestContext.RouteData.Values["action"].ToString());
            requestContextRoute = sb.ToString();

            if (string.IsNullOrWhiteSpace(area))
            {
                passedInRoute = "/" + controller + "/" + action;
            }
            else
            {
                passedInRoute = area + "/" + controller + "/" + action;
            }

            //  Are the 2 routes the same?
            if (!requestContextRoute.Equals(passedInRoute, StringComparison.OrdinalIgnoreCase))
            {
                result = null;
            }

            return result;
        }
24
Big Daddy

Vous devez vérifier dans votre contrôleur ou voir quel élément de menu est actif en fonction de l'URL actuelle:

J'ai une méthode d'extension similaire à celle-ci:

public static string MakeActiveClass(this UrlHelper urlHelper, string controller)
{
    string result = "active";

    string controllerName = urlHelper.RequestContext.RouteData.Values["controller"].ToString();

    if (!controllerName.Equals(controller, StringComparison.OrdinalIgnoreCase))
    {
        result = null;
    }

    return result;
}

Vous pouvez l'utiliser dans votre vue comme ceci:

<!-- Make the list item active when the current controller is equal to "blog" -->
<li class="@Url.MakeActive("blog")">
   <a href="@Url.Action("index", "blog")">....</a>
</li>
28
SebastianStehle

Le JavaScript ne fonctionne pas car la page est rechargée après son exécution. Donc, il définit correctement l'élément actif, puis la page se charge car le navigateur suit le lien. Personnellement, je supprimerais le JavaScript que vous avez car il ne sert à rien. Pour ce faire côté client (au lieu du code côté serveur que vous avez), vous avez besoin de JavaScript pour définir l'élément actif lors du chargement de la nouvelle page. Quelque chose comme:

$(document).ready(function() {
    $('ul.nav.navbar-nav').find('a[href="' + location.pathname + '"]')
        .closest('li').addClass('active');
});

Je recommande d'ajouter un identifiant ou une autre classe à votre barre de navigation afin que vous puissiez être sûr d'avoir sélectionné le bon.

18

Simplement vous pouvez le faire dans n'importe quelle vue 

<ul class="nav navbar-nav">
    @Html.NavigationLink("Link1", "Index", "Home")
    @Html.NavigationLink("Link2", "Index", "Home")
    @Html.NavigationLink("Link3", "Index", "Home")
    @Html.NavigationLink("Links with Parameter", "myAction", "MyController", new{ id=999}, new { @class= " icon-next" })
</ul>

Après avoir ajouté cette méthode à une nouvelle classe ou à une classe HtmlExtensions existante

public static class HtmlExtensions
{
    public static MvcHtmlString NavigationLink(this HtmlHelper html, string linkText, string action, string controller, object routeValues=null, object css=null)
    {
        TagBuilder aTag = new TagBuilder("a");
        TagBuilder liTag = new TagBuilder("li");
        var htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(css);
        string url = (routeValues == null)?
            (new UrlHelper(html.ViewContext.RequestContext)).Action(action, controller)
            :(new UrlHelper(html.ViewContext.RequestContext)).Action(action, controller, routeValues);

        aTag.MergeAttribute("href", url);
        aTag.InnerHtml = linkText;
        aTag.MergeAttributes(htmlAttributes);

        if (action.ToLower() == html.ViewContext.RouteData.Values["action"].ToString().ToLower() && controller.ToLower() == html.ViewContext.RouteData.Values["controller"].ToString().ToLower())
            liTag.MergeAttribute("class","active");

        liTag.InnerHtml = aTag.ToString(TagRenderMode.Normal);
        return new MvcHtmlString(liTag.ToString(TagRenderMode.Normal));
    }
}
6
Moji

La chose la plus simple à faire est d’envoyer un paramètre ViewBag à partir de vos contrôleurs comme suit:

public ActionResult About()
    {            
        ViewBag.Current = "About";
        return View();
    }


    public ActionResult Contact()
    {            
        ViewBag.Current = "Contact";
        return View();
    }

Dans la page cshtml, procédez comme suit:

           <ul class="nav navbar-nav">                    
                <li class="@(ViewBag.Current == "About" ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
                <li class="@(ViewBag.Current == "Contact" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
            </ul>

Courtoisie de @Damith dans ici

6
Mahib

Je crois que vous avez la sélection en arrière. Vous ajoutez la classe, puis vous la supprimez de la fratrie, et je pense que supprimer la seconde cause le problème. Pouvez-vous essayer d'inverser cela pour qu'il soit:

<script type="text/javascript">

    $(function () {
        $('.navbar-nav li').click(function () {
            $(this).siblings().removeClass('active');
            $(this).addClass('active');
        });
    });

</script>
2
tlbignerd

Votre fonction javascript devrait fonctionner correctement ... Le problème est que vos liens sont dirigés vers un contrôleur et rechargent la page entière. Afin d'éviter ce problème, vous pouvez rendre le contenu de votre corps sous forme de vue partielle. Ainsi, les éléments de la barre de navigation ne seront pas rechargés. Vous ne devriez pas avoir à écrire une fonction pour gérer les événements dom - c’est à cela que sert javascript.

Pour voir ce que je veux dire, changez votre code:

<li><a href="~/Home/About">About</a></li>
<li><a href="~/Student">Students Sample</a></li>

à:

 <li><a href="">About</a></li>
 <li><a href="">Students Sample</a></li>
0
jmyns