admin管理员组

文章数量:1410737

I need to change the navbar link color when I'm navigating through my Razor-Pages. I tried to use JavaScript, but it seems that the pages are getting rerendered every time when I go to another page and I'm not able to toggle my elements.

Here is what I have tried so far:

Nav bar links

<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between ml-5">
                 <ul class="navbar-nav flex-grow-1">
                    <li class="nav-item">
                        <a class="nav-link active-link" asp-area="" asp-page="/Index">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" asp-area="" asp-page="/Privacy">Privacy</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" asp-page="/Movies/Index">Movies</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" asp-page="/Genres/Index">Genres</a>
                    </li>
                </ul>
</div>

site.js

const links = document.querySelectorAll('.nav-link');
let currentActive = document.querySelector('.active-link');

const changeClass = (e) => {
    //e.preventDefault();
    currentActive.classList.remove('active-link');
    e.target.classList.add('active-link');
};

links.forEach((el) => el.addEventListener('click', changeClass));

Here I save the current active link in my js and when I navigate to another page, the page gets rerendered and my js file is reloaded again so that the value that I have previously is set back to the default active link.

What I have:

What I want:

I found one possible solution, but it seems to be a bit of hard-coding and working around, I believe there should be a better way.

P.S. Ideally, a solution using JavaScript would be best, however, I'm not sticking to anything here.

I need to change the navbar link color when I'm navigating through my Razor-Pages. I tried to use JavaScript, but it seems that the pages are getting rerendered every time when I go to another page and I'm not able to toggle my elements.

Here is what I have tried so far:

Nav bar links

<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between ml-5">
                 <ul class="navbar-nav flex-grow-1">
                    <li class="nav-item">
                        <a class="nav-link active-link" asp-area="" asp-page="/Index">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" asp-area="" asp-page="/Privacy">Privacy</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" asp-page="/Movies/Index">Movies</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" asp-page="/Genres/Index">Genres</a>
                    </li>
                </ul>
</div>

site.js

const links = document.querySelectorAll('.nav-link');
let currentActive = document.querySelector('.active-link');

const changeClass = (e) => {
    //e.preventDefault();
    currentActive.classList.remove('active-link');
    e.target.classList.add('active-link');
};

links.forEach((el) => el.addEventListener('click', changeClass));

Here I save the current active link in my js and when I navigate to another page, the page gets rerendered and my js file is reloaded again so that the value that I have previously is set back to the default active link.

What I have:

What I want:

I found one possible solution, but it seems to be a bit of hard-coding and working around, I believe there should be a better way.

P.S. Ideally, a solution using JavaScript would be best, however, I'm not sticking to anything here.

Share Improve this question edited Apr 10, 2021 at 21:52 Miraziz asked Apr 10, 2021 at 19:33 MirazizMiraziz 5091 gold badge9 silver badges21 bronze badges 2
  • Are you using some frontend framework? Or is it plain HTML and JS, where the header is in each html page implemented? – Jozott Commented Apr 10, 2021 at 20:24
  • Well, I'm using the default UI setup which is bootstrap, and there is also jquery, but for this problem, I'm using plain js because I'm just playing around and want to see how it will work for my uping project so that I can decide whether I will move on with pure js or something else. – Miraziz Commented Apr 10, 2021 at 21:41
Add a ment  | 

3 Answers 3

Reset to default 7

Use the DOMContentLoaded event rather than the click event. That way the change will be applied to the actual page after it has rendered. At the moment, you are applying the change to the links on the page that you are navigating from:

document.addEventListener('DOMContentLoaded', () => {
    document.querySelectorAll('.nav-link').forEach(link => {
        if (link.getAttribute('href').toLowerCase() === location.pathname.toLowerCase()) {
            link.classList.add('active-link');
        } else {
            link.classList.remove('active-link');
        }
    });
})

Doesn't necessarily need javascript.
TagHelpers can be used for a server-sided solution, see my answer on a similar question here.

For example, the tag helper uses a custom attribute on the nav bar elements to describe which page each link corresponds to. Then when the tag helper processes the attribute, it pares the value with the current address, and if it matches, it adds the active class.

It also removes the attribute so that it's not available to the user in the response HTML. Doing it server sided also ensures that the highlight will be available for users with javascript disabled.

I had the same problem and started with this approach: Create a different layout for each page. Every layout has highlighted the link of interest. The issue was that you have many layouts with small changes, only in the nav bar links.

So, I decided to improve the solution, I finally it was much more simple than expected:

Here the snippet of the second approach:

// _Layout.cshtml

<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">VS22Netcore01</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul id="mainMenu" class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            **<a id="linkHome"** class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            **<a id="linkPrivacy"** class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                        <li class="nav-item">
                            **<a id="linkAbout"** class="nav-link text-dark" asp-area="" asp-page="/About">Acerca de</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()  <!-- inserta la pagina en el container} -->
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - VS22Netcore01 - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    **@await RenderSectionAsync("Scripts", required: true)**
</body>

Please, note the code betwwen double asteriks.

Then, In each content page I added something like this:

//Privacy.cshtml, a sample page
@page
@model PrivacyModel
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>



@section Scripts 
{
<script>        
    **$('#linkPrivacy').removeClass('text-dark');
    $('#linkPrivacy').addClass('text-info');**
</script>
}

As you can see, The script in each content page changes the style of the links. In that way you have different "slightly" pages.

Regards

本文标签: Change active navbar link using JavaScript in ASPNET Core Razor PagesStack Overflow