Navbar active class resets on page load

本秂侑毒 提交于 2019-12-11 07:54:30

问题


Using bootstrap 4 and asp.net core for a personal project I've been tinkering with for the past couple of months. I've got a navbar in my _Layout that is shared across my entire site. I've also got some css that styles the navbar link text.

I'm trying to change the active class on the links so the currently-visited controller is highlighted with a different color. I'm using js to do this. The color is changing initially, so I'm sure that the js is adding the active class to the new link and removing it from the previous active link, but when the page finishes loading, they reset and the active class goes back to Home.

Here is my navbar in _Layout.cshtml:

<nav class="navbar navbar-toggleable-md navbar-inverse bg-inverse">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggler" aria-controls="navbarToggler" aria-expanded="false" aria-label="Toggle navigation">
    <img src="~/images/logo1.png" width="40" height="40" alt="" />
</button>
<div class="collapse navbar-collapse" id="navbarToggler">
    <ul class="nav navbar-nav mr-auto mt-2 mt-lg-0">
        <li class="nav-item active">
            <a class="nav-link" asp-action="Index" asp-controller="Home">Home<span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item">
            <a class="nav-link" asp-action="Index" asp-controller="aaaa">Aaaa</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" asp-action="Index" asp-controller="bbbb">Bbbb</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" asp-action="Index" asp-controller="cccc">Cccc</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" asp-action="Index" asp-controller="dddd">Dddd</a>
        </li>
    </ul>
    <form class="form-inline my-2 my-lg-0">
        <button class="btn btn-outline-danger btn-sm"
                type="submit" asp-action="Login" asp-controller="Account">
            Login
        </button>
    </form>
</div>

Here is the js that I'm declaring in the @scripts section of _Layout:

$( '.navbar-inverse .navbar-nav a' ).on( 'click', function () {
    $( '.navbar-inverse .navbar-nav' ).find( 'li.active' ).removeClass( 'active' );
    $( this ).parent( 'li' ).addClass( 'active' );
});

And my css:

.navbar-inverse .navbar-nav .open > .nav-link, 
.navbar-inverse .navbar-nav .active > .nav-link, 
.navbar-inverse .navbar-nav .nav-link.open, 
.navbar-inverse .navbar-nav .nav-link.active {
    color: yellow;
}

Why is the active link being reset when the new page loads? I know the js is working because while the page is loading, "Home" is not yellow anymore, but the new link I clicked in the navbar is yellow. But when the loading is complete, the yellow goes back to Home. Any insights would be appreciated, I'm rather new at software development.


回答1:


You're setting active on click. However, when the browser actually goes to that URL following the click, a completely different view is rendered. Therefore, there's no concept of anything having been set a certain way or done previously.

Instead, you need to either have your JS run onload, or simply just send the HTML with the correct item active in the first place, and throw away the JS. The easiest way to do that is something like:

@{ string url; }

Then for each nav link:

@{ url = Url.Action("Foo", "Bar"); }
<li class="@(Request.Path.StartsWith(url) ? "active" : null)">
    <a href="@url">Foo</a>
</li>

Setting the url variable is mostly just a way to not repeat yourself with the action/controller for the link, since you need the link URL in two different places.

The meat is in the ternary. If the current URL path starts with this link's URL (which should cover both the scenario of being equal to and just being a parent of the current URL), then you apply the active class.

EDIT

Because of using StartsWith, a link for "Home" will basically always be set as active, since every URL would start with /. You probably want to make an exception on that link and instead just do:

@{ url = Url.Action("Index", "Home"); }
<li class="@(Request.Path == url ? "active" : null)">
    <a href="@url">Home</a>
</li>

Then, that link will only be marked active if the URL is actually /.




回答2:


Thanks to @Chris Pratt for his guidance. I got this working albeit with a couple of changes, possibly due to me changing my mind on the navbar and moving to a tabbed navbar (like Twitter's mobile app uses). Here's my navbar code in _Layout.cshtml:

<!--navbar-->
@{ string url; }

<ul class="nav navbar-dark bg-dark nav-tabs nav-fill">
    @{ url = Url.Action("Index", "Home"); }
    <li class="nav-item">
        <a class="nav-link @(Context.Request.Path == url ? "active" : null)" href="@url">Home</a>
    </li>
    @{ url = Url.Action("Index", "Spells"); }
    <li class="nav-item">        
        <a class="nav-link @(Context.Request.Path.StartsWithSegments(url) ? "active" : null)" href="@url">Spells</a>
    </li>
    @{ url = Url.Action("Index", "Crits"); }
    <li class="nav-item">        
        <a class="nav-link @(Context.Request.Path.StartsWithSegments(url) ? "active" : null)" href="@url">Crits</a>
    </li>
    @{ url = Url.Action("Index", "Journal"); }
    <li class="nav-item">        
        <a class="nav-link @(Context.Request.Path.StartsWithSegments(url) ? "active" : null)" href="@url">Journal</a>
    </li>
</ul>

Now that the active class switching is working as expected, I can add some styling, and replace the text with icons that I'll make.

Gave you an upvote, Chris Pratt, but my rep is too low to show it publicly for now. Thanks again.



来源:https://stackoverflow.com/questions/48545039/navbar-active-class-resets-on-page-load

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!