Updating the active navbar link with JavaScript in ASP.NET Core Razor Pages

When navigating through my Razor Pages, I need to dynamically change the color of the navbar links. I attempted using JavaScript, but encountered issues with the pages getting rerendered each time, preventing me from toggling the elements.

Here's what I have experimented with:

Navbar 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));

In this setup, I store the active link in my JavaScript file and encounter challenges when the page reloads and the script is reloaded, leading to the reset of the active link to default.

My Current Setup: https://i.sstatic.net/oZHjv.gif

Desired Output: https://i.sstatic.net/AWmKs.gif

I stumbled upon a potential solution on Stack Overflow, however, it appears to involve a workaround that feels like hard-coding. I am open to exploring better alternatives.

P.S. While a JavaScript solution would be preferred, I am flexible and open to alternative approaches.

Answer №1

Opt for the DOMContentLoaded event over the click event. By doing so, the change will take effect on the actual page after it has finished rendering. Currently, you are making changes to the links on the page you are navigating away 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');
        }
    });
})

Answer №2

There is no absolute need for javascript.
TagHelpers offer a server-side alternative, as seen in my response to a similar query here.

For instance, the tag helper utilizes a custom attribute on the navigation bar elements to specify which page each link corresponds to. As the tag helper processes the attribute, it checks against the current address and adds the active class if there's a match.

The attribute is then removed to prevent user access in the response HTML. Conducting this procedure server-side guarantees that even users with disabled javascript can still benefit from the highlighting feature.

Answer №3

I encountered a similar issue and initially tackled it by creating separate layouts for each page, with the link of interest highlighted in each layout. However, I soon realized that this approach led to multiple layouts with minor changes, particularly in the navigation bar links.

After pondering on how to enhance the solution, I discovered a much simpler alternative than anticipated:

Below is the snippet showcasing the revised 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>

    ....

Please, take note of the code enclosed within double asterisks.

Subsequently, in every content page, I integrated something akin to the following:

//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 illustrated above, the script within each content page alters the style of the links, resulting in subtly varied pages.

Best regards

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is the 'wait > remaining' condition ever satisfied in the throttle function of underscore.js?

Check out the library code at line 860: https://github.com/jashkenas/underscore/blob/master/underscore.js if (remaining <= 0 || remaining > wait) Under what circumstance would the second part of this statement be true? Background - This is my firs ...

Highlighting text in React using hover effects on list elements

Imagine having HTML / JSX structured like this: <ul> <li>First point in list</li> <li>Second point in list</li> </ul> and the goal is to highlight a contiguous range that spans multiple list items: <ul> < ...

A method for automatically refreshing a webpage once it switches between specific resolutions

On my page www.redpeppermedia.in/tc24_beta/, it functions well at a resolution of over 980px. However, when the resolution is brought down to 768px, the CSS and media queries alter the layout. But upon refreshing the page at 768px, everything corrects itse ...

Incorporating external scripts into Angular HTML templates

I recently upgraded to a premium version of Polldaddy and received a script tag for embedding (without the correct id). <script type="text/javascript" charset="utf-8" src="http://static.polldaddy.com/p/0000000.js"></script> I am trying to loa ...

Generate an array using hyperlinks within a list item created by the user

In the process of developing a program, I have included a feature where users can drag and drop .wav files into a playlist-container. These files are then played in the order they are arranged within the playlist-container. Currently, I am working on imple ...

What is the best way to effectively utilize bootstrap and JavaScript together?

I've been trying to implement some JavaScript on top of Bootstrap 5, but it doesn't seem to be working. I'm not sure if I'm doing something wrong with the JavaScript itself, or if there's an issue with how it's interacting wit ...

How can I send two responses in a single POST request using node.js?

Below is my router setup for handling responses: questionRouter.post('/questionsReply', (req, res) => { twilioResp(req, res); var newResponse = new Response(req.body); newResponse.save((err, data) => { if (err) return handleDBError(er ...

Vuetify's Handy Helper Classes

Hey everyone, I'm working on a vuetify project and I need to convert inline styles to utility classes (if possible) font-size: 24px; font-weight :600 I checked the documentation and noticed that it only provides options for setting size and weight wi ...

What is the process for accessing and storing an uploaded image in a Next.js application?

How can I retrieve an uploaded image in a next.js API route and save it to the public folder? My frontend is all set up, and I'm currently uploading images to an endpoint using plain JavaScript. Below is the onSubmit function for uploading images. Ple ...

How to specify a single kind of JavaScript object using Typescript

Let's say we have an object structured as follows: const obj = [ { createdAt: "2022-10-25T08:06:29.392Z", updatedAt: "2022-10-25T08:06:29.392Z"}, { createdAt: "2022-10-25T08:06:29.392Z", animal: "cat"} ] We ...

What Makes Bootstrap Spinner Ineffective in High-Performance Computing Scenarios

I understand that Javascript operates on a single thread, but I am puzzled as to why the spinner is not showing or hiding before/after a compute-intensive task in the following code. Here is the outline of the code: showSpinner(); computeIntensiveTask(); ...

AngularJS - Issue: [ng:areq] The 'fn' argument provided is not a function, instead it is a string

I encountered an issue: Error: [ng:areq] Argument 'fn' is not a function, received string Despite following the recommendations of others, I still have not been able to resolve the problem. Below is the code snippet in question: controller. ...

Unable to observe the transition of opacity changes in threeJS for tweens

<script type="importmap"> { "imports": { "three": "https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f2869a809797b284c2dcc3c4c0dcc2">[email protected]& ...

Display an empty string when a value is NULL using jQuery's .append() function

To set an HTML value using the .append() function, I need to include AJAX data values. If the data set contains a null value, it will show as 'null' in the UI. I want to remove that 'null' and display it as blank. However, I can't ...

Building a dynamic webpage using AJAX, MVC, and web APIs to generate a div element filled

I'm currently working with a restful API, MVC, and ajax. My goal is to retrieve data from the backend and then display images within certain div elements. The expected outcome should resemble this example: https://i.stack.imgur.com/BFqWL.png This sni ...

What is the best way to use Jquery ScrollTo() to navigate to an element on a page using a class selector

Building on the information from this source, I have a question: How can I resolve the same issue using a class selector like $('.class')? I am encountering an error message that says Uncaught TypeError: undefined is not a function This occurs ...

Unable to access filteredItems from custom popup in uib-typeahead retrieval process

Issue with Retrieving Filtered Items from ng-repeat in Controller using $scope Despite trying to fetch filtered items from ng-repeat, the value of $scope.filteredItems appears as undefined when I log it to the console. I attempted to implement the solutio ...

Finding your way to a particular section within a webpage through an external source

Hey there! I'm currently working on creating a link that will direct users to a specific section within my webpage. For example, redirecting them to https://blabla.github.io/my-website. My code is quite straightforward and it functions properly when ...

What is the best way to sort ISO DateTime objects that fall outside of a particular time frame?

I'm currently working on a project that involves a list of objects with properties for startTime and endTime, all in ISO format. Here's a snippet of the list: list = [ { startTime: '2022-06-26T10:00:00.000Z', endTime: '2022- ...

Struggling to get the fluid image feature to work properly on Bootstrap 4

I seem to be facing an issue with creating responsive images using Bootstrap 4. Whenever I view the code below on a browser, I see three images in the navbar at the top left corner. Unfortunately, these images do not scale down in size when viewed on mobil ...