Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep the active menu item highlighted when visiting pages in ASP.Net MVC 5 application?

So, I have one ASP.Net MVC 5 application. In that one of page hasfour menu items. When page loads first menu item is selected by default (so it should be highlighted as soon as the page loads). And now as soon as user clicks on any other menu, that other menu should be in highlighted stage, so that user knows which menu he is currently on. Below is my attempt:

My thinking:

a. add a click event on the ul tag.

b. when clicked find "active" class inside ul tag and remove it.

c. now add active class to the source of click event (which means the li tag on which user clicked).

Issue:

The selected/clicked menu gets highlighted for a second, and then automatically first menu gets highlighted. So as soon as the whole page corresponding to the newly clicked menu item reloads the first menu item gets highlighted back.

My Attempt

P.S: This is a partial View, And all redirects will load this partial view afresh.

@if (Request.IsAuthenticated)
{
    <ul style="list-style-type:none;">
        <li class="active setBtnMargin">
            <a href="@Url.Action("Index", "Resume")" class="btn btn-block">My Resume </a>
        </li>
        <li class="setBtnMargin">
            <a href="@Url.Action("Index", "CoverLetter")" class="btn btn-block">My Cover Letter </a>
        </li>
        <li class="setBtnMargin">
            <a href="@Url.Action("Index", "Home")" class="btn btn-block">My Account </a>
        </li>
        <li class="setBtnMargin">
            <a href="@Url.Action("Index", "Home")" class="btn  btn-block">Get Rewards </a>
        </li>
    </ul>
}

<script>
// ATTEMPT 1
    $("ul").on("click", "li", function () {
        $('ul li').removeAttr('active');
        $(this).addClass('active');
    });

// ATTEMPT 2
    //$("li").click(function () {
    //    //$("ul li").removeClass("active");
    //    $(this).addClass("active");
    //});
</script>

EDIT 1

So the problem is as the page gets redirected. The active tag again gets appened to the first menu item when entire DOM gets reloaded because all the landing pages use the same partial view.

like image 992
Unbreakable Avatar asked Aug 10 '17 02:08

Unbreakable


2 Answers

Everytime you click on a link, it does a page redirect, and it doesn't matter what changes you've made with jQuery, it always fetch this partial view, and in this partial view, you have active class on the first link, that is why it always highlights the first link.

What you have to do is write an HtmlHelper that will add the class "active" to current link on each page load. Create a folder called Helpers under your project and add a custom HtmlHelper class.

using System;
using System.Web.Mvc;

public static class ActiveMenuHelper
{
    public static MvcHtmlString MenuLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string areaName)
    {
        var currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
        var currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");
        var currentArea = htmlHelper.ViewContext.RouteData.DataTokens["area"];

        var builder = new TagBuilder("li")
        {
            //InnerHtml = htmlHelper.ActionLink(linkText, actionName, controllerName).ToHtmlString()
            InnerHtml = "<a href=\"" + new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(actionName, controllerName, new { area = areaName }).ToString() + "\">" + linkText + "</a>"
        };

        if (String.Equals(controllerName, currentController, StringComparison.CurrentCultureIgnoreCase) && String.Equals(actionName, currentAction, StringComparison.CurrentCultureIgnoreCase))
            builder.AddCssClass("active");

        return new MvcHtmlString(builder.ToString());
    }
}

and then in your partial view:

@using YourProjectName.Helpers

<ul>
    @Html.MenuLink("Resume", "Index", "Resume", "" )
    @Html.MenuLink("Cover Letter", "Index", "CoverLetter", "" )
</ul>

You might not need the area, that is why you can leave it blank, i put it in here just in case.

like image 92
Mindless Avatar answered Sep 27 '22 00:09

Mindless


Try adding this to your shared view . normally "_Layout".

@{ 
    string pageUrl = Request.Url.PathAndQuery.ToString();
}

and instead of adding "active" class from the html markups, add conditional statement that will check the pageUrl just like the code below.

@if (Request.IsAuthenticated)
{
    <ul style="list-style-type:none;">
        <li class="@(pageUrl.ToLower().Contains("/index/Resume") ? "active" : string.Empty) setBtnMargin">
            <a href="@Url.Action("Index", "Resume")" class="btn btn-block">My Resume </a>
        </li>
        <li class="@(pageUrl.ToLower().Contains("/index/CoverLetter") ? "active" : string.Empty) setBtnMargin">
            <a href="@Url.Action("Index", "CoverLetter")" class="btn btn-block">My Cover Letter </a>
        </li>
        <li class="@(pageUrl.ToLower().Contains("/index/Home") ? "active" : string.Empty) setBtnMargin">
            <a href="@Url.Action("Index", "Home")" class="btn btn-block">My Account </a>
        </li>
        <li class="@(pageUrl.ToLower().Contains("/index/Home") ? "active" : string.Empty) setBtnMargin">
            <a href="@Url.Action("Index", "Home")" class="btn  btn-block">Get Rewards </a>
        </li>
    </ul>
}
like image 21
JF-Mechs Avatar answered Sep 26 '22 00:09

JF-Mechs