The icon remains unchanged upon clicking the button for the second time

https://i.sstatic.net/7b8XY.png

Above you see the default icon. It works perfectly when I click to open the categories.

https://i.sstatic.net/4bJjF.png

However, an issue arises when I click on the dropdown button again to close it. The dropdown closes but the icon fails to return to its original position i.e. angle-down.

https://i.sstatic.net/gFjtL.png

If I click anywhere outside the categories button to close the dropdown, the icon changes back to angle-down. Yet, clicking on the button doesn't revert the icon to its default state.

Here is my HTML code:

<button class="dropbtn"> 
     <i class="fa-solid fa-border-all"></i>
     <p>Browse All Categories</p>
     <i class="smallicon fa-solid fa-angle-down"></i>
</button>

This is my JS code:

document.querySelector('.dropbtn').addEventListener('click', function(event) {
            event.stopPropagation(); 
            var dropdownContent = this.nextElementSibling;
            var angleIcon = this.querySelector('.fa-angle-down');
    
            if (dropdownContent.style.display === 'block') {
                dropdownContent.style.display = 'none';
                angleIcon.classList.remove('fa-angle-up');
                angleIcon.classList.add('fa-angle-down');
            } else {
                dropdownContent.style.display = 'block';
                angleIcon.classList.remove('fa-angle-down');
                angleIcon.classList.add('fa-angle-up');
            }
        });
    
        // Close dropdown when clicking outside
        document.addEventListener('click', function(event) {
            var dropdowns = document.querySelectorAll('.dropdown-content');
            dropdowns.forEach(function(dropdown) {
                if (dropdown.style.display === 'block' && !event.target.closest('.dropdown')) {
                    dropdown.style.display = 'none';
                    var angleIcon = dropdown.previousElementSibling.querySelector('.fa-angle-up');
                    if (angleIcon) {
                        angleIcon.classList.remove('fa-angle-up');
                        angleIcon.classList.add('fa-angle-down');
                    }
                }
            });
        });

Answer №1

Here is a recommended approach:

document.addEventListener('DOMContentLoaded', function() {
    const dropbtn = document.querySelector('.dropbtn');
    const dropdownContent = document.querySelector('.dropdown-content');
    const angleIcon = dropbtn.querySelector('.fa-angle-down');

    dropbtn.addEventListener('click', function(event) {
        event.stopPropagation();
        dropdownContent.classList.toggle('show');
        angleIcon.classList.toggle('fa-angle-up');
        angleIcon.classList.toggle('fa-angle-down');
    });

    document.addEventListener('click', function(event) {
        if (!event.target.closest('.dropdown')) {
            dropdownContent.classList.remove('show');
            angleIcon.classList.remove('fa-angle-up');
            angleIcon.classList.add('fa-angle-down');
        }
    });
});
.dropdown {
    position: relative;
    display: inline-block;
  }

  .dropdown-content {
    display: none;
    position: absolute;
    background-color: #f9f9f9;
    min-width: 160px;
    box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
    z-index: 1;
  }

  .dropdown-content a {
    color: black;
    padding: 12px 16px;
    text-decoration: none;
    display: block;
  }

  .dropdown-content a:hover {
    background-color: #f1f1f1;
  }

  .show {
    display: block;
  }
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">

<div class="dropdown">
  <button class="dropbtn"> 
    <i class="fa-solid fa-border-all"></i>
    <p>Browse All Categories</p>
    <i class="fa-solid fa-angle-down"></i>
  </button>
  <div class="dropdown-content">
    <a href="#"><i class="fas fa-car"></i> Autos</a>
    <a href="#"><i class="fas fa-laptop"></i> Electro</a>
    <a href="#"><i class="fas fa-pizza-slice"></i> Food</a>
  </div>

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

Configuration file stored within the node_modules directory

I have developed a generic npm package that contains my business logic. However, I require access to some information stored in my google cloud storage configuration files. How can I retrieve this data when my package is located within the node_modules fol ...

Tips for utilizing a forward slash in route parameters

My GET REST service requires parameters containing slashes. The URL structure is as follows: "/term/:term/amount/:amount" where :term can include a string with slashes, such as "para/5MG". I am using express for my API and would like to avoid rewriting i ...

The firebase collection's model doesn't include an add function within its nested collection

I'm currently developing an application where I aim to utilize Firebase for real-time data storage within the context of the Backbone framework. The issue I am facing is as follows: I have a sub-level model and collection, both of which are standar ...

Utilizing Google Analytics within an Angular Single Page Application

After implementing Google Analytics (GA) in my Angular single page application and placing the tracking code at the bottom of the main index.html, I encountered an issue regarding incorrect pageview results. <script> (function(i,s,o,g,r,a,m){i["Go ...

Experiencing an issue in Test Cafe when attempting to click on an invisible link using the Client Function

I need to find a way to click on an invisible button in HTML. I attempted to use ClientFunction, however I encountered an error related to the element. import { Selector,ClientFunction } from 'testcafe'; fixture('Clicking Invisible link&apo ...

List-style-type outside of a table's boundaries

I recently experimented with using <ol> as list elements within a table in order to dynamically insert new table rows. <table> <thead> <tr> <th>head</th> <th>head</th> <th>h ...

How can I effectively organize an Angular2 component library for optimal efficiency?

Looking to develop an Angular2 datepicker component with the intention of releasing it and using it in multiple projects. Wondering about the best way to structure the project for this specific purpose compared to a typical Angular2 project created with an ...

Consolidate HTML project into a unified HTML file

In my current project, I am working with a static HTML report that is organized in the structure outlined below: 1.css 2.font 3.js 4.pages 5.attachments 6.index.html I would like to know how I can combine all these elements to create a unified 'repor ...

Access external variables in next.js outside of its environment configuration

Currently, I am developing my application using next js as the framework. While my environment variables work smoothly within the context of next js, I am facing a challenge when it comes to utilizing them outside of this scope. An option is to use dotenv ...

ignore any anchors beyond the second index

I am working with a django-qcm that has dynamic sections triggered by anchors and utilizes the scroll snap type property. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv ...

An issue has been detected with the date picker functionality on Internet Explorer

I have the following code in my header: <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js">&l ...

What is causing the extra space at the top of my page from the contextual menu?

My goal is to implement a contextual menu for my HTML web application. Strangely, when the menu is hidden, there is no space at the top of the page, but once it's activated, some empty space appears. Contextual menu in disabled state: https://i.sstat ...

Button click does not fill in Jquery Datepicker?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <link type="text/css" href="Styles/Site.css" rel="Stylesheet" ></link > <script type="text/javascript" src= ...

What steps can be taken to address a TypeScript error when a function's parameters may be of two different types?

I'm facing an issue with a simple function that retrieves the address as a string interface AddressType1 { city: string | null; state: string | null; postalCode: string | null; } interface AddressType2 { city: string | null; region: strin ...

Display loading spinner in Material-UI Table while fetching data

Is it possible to display a Circular progress indicator while waiting for data to populate the table? How can this be accomplished? Currently, the table shows No records to display until the data is retrieved from the server. https://i.stack.imgur.com/Ljq ...

Having Trouble Creating the production APK in React Native

Having trouble generating an APK after following the steps outlined in the documentation. Build Failed even though I tried: 1. cd android 2. gradlew clean "build Successful" 3. gradlew assembleRelease "BUILD FAILED" with this Erro ...

The key length specified in crypto.createCipheriv is not valid

After utilizing NodeJS v8.11.0, I managed to create a base64-encoded key with the following code: const secret = 'shezhuansauce'; const key = crypto.createHash('sha256').update(String(secret)).digest('base64'); //output is RE ...

Iframe Loading at Lightning Speed

I have set up a script to load my iframe, but I noticed that the script loads the iframe content too quickly. Is there a way for me to configure it to preload all CSS images and content in the background before showing the full iframe content? Here is my ...

"Troubleshooting the issue of multiple root nodes in Vue.js even when there

While working on my Vue.js code, I encountered an issue with a v-for loop. Despite having only one HTML node within it, Vue is giving me two errors: vue.js:597 [Vue warn]: Error compiling template: <div id="products" v-for="p in productList"> ...

Utilizing useEffect with custom hooks results in endless calls

During the process of restructuring the code to retrieve account information, an issue arose where the page was being continuously rerendered. Below is a custom hook created to fetch account details. //flattenTree function returns an array containing flat ...