Steps to automatically hide dropdowns when a menu item is selected

I am working on a dropdown menu using NUXT JS and Tailwind CSS. However, I have encountered an issue with nuxt-js - since it does not change pages using SSR, the dropdown does not close when navigating to a new page. How can I make the dropdown automatically close when a menu item is clicked?

Here is the template:

      <!-- dropdown -->
      <button class="mt-1 block px-2 py-1 text-white font-semibold rounded hover:bg-gray-800 sm:mt-0 sm:ml-2"
        type="button" v-on:click="toggleDropdown()" ref="btnDropdownRef">
        Applications
      </button>
      <div v-bind:class="{'hidden': !dropdownPopoverShow, 'block': dropdownPopoverShow}"
        class="bg-gray-800 w-full md:w-1/5 text-white z-50 float-left py-2 list-none text-left rounded shadow-lg mt-1"
         ref="popoverDropdownRef">
        <NuxtLink class="mt-1 font-semibold block px-2 py-1 text-white  rounded hover:bg-gray-800 sm:mt-0 sm:ml-2" to="/applications/education">
        education
        </NuxtLink>
        <NuxtLink class="mt-1 font-semibold block px-2 py-1 text-white  rounded hover:bg-gray-800 sm:mt-0 sm:ml-2" to="/applications/lifescience">
        life sciences 
        </NuxtLink>
        ...
      </div>

And here is the script:

<script>
  import {
    createPopper
  } from "@popperjs/core";

  export default {
    data() {
      return {
        isOpen: false,
        dropdownPopoverShow: false,
      }
    },
    methods: {
      toggleDropdown: function () {
        if (this.dropdownPopoverShow) {
          this.dropdownPopoverShow = false;
        } else {
          this.dropdownPopoverShow = true;
          createPopper(this.$refs.btnDropdownRef, this.$refs.popoverDropdownRef, {
            placement: "bottom-start"
          });
        }
      }
    }
  }
</script>

Answer №1

After some consideration, I ultimately decided to implement the watch route approach

 watch: {
    '$route' () {
      // Disabling the dropdown popover
      this.dropdownPopoverShow = false,  
      // Hiding the mobile menu when page changes
      this.isOpen = false
    }

Answer №2

To ensure a method runs every time a page is changed, utilize the afterEach hook on the Vue router instance. It's advisable to integrate this functionality as a plug-in in Nuxt and transfer `dropdownPopoverShow` from your navigation component to the store.

Move the `dropdownPopoverShow` property to the store so it can be accessed outside of the navigation component.

export const state = () => ({
  dropdownPopoverShow: false
})

export const mutations = {
  toggleDropdown(state) {
    // Instead of using an 'if/then' statement, directly toggle the Boolean value
    state.dropdownPopoverShow = !state.dropdownPopoverShow
  },
  hideDropdown(state) {
    state.dropdownPopoverShow = false
  }
}

In your navigation component, invoke the mutation present in the store.

methods: {
  toggleDropdown() {
    this.$store.commit('toggleDropdown')
  }
}

Lastly, create a plug-in that resets `dropdownPopoverShow` to false after each route change.

// plugins/hideDropdown.js:
export default async ({ app, store }) => {
  app.router.afterEach((to, from) => {
    store.commit('hideDropdown')
  });
}

Don't forget to include the plug-in in your nuxt config:

plugins: [ { src: '~/plugins/hideDropdown.js', mode: 'client' } ]

Answer №3

Using Composition API

const currentRoute = useRoute();

watch(currentRoute, () => {
  this.dropdownPopoverShow = false, 
  this.isOpen = false
});

When utilizing Option API

watch: {
  '$route' () {
    this.dropdownPopoverShow = false,  
    this.isOpen = false
}

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

Tips for sending a command to the server using the ssh2-promise package in Node.js

In my current code, I am utilizing an SSH library to establish a connection to a server, create a shell session, and send a password to authenticate. However, I am encountering an issue where the password is not being sent as intended. Upon some debugging ...

Utilizing JSX within this.state results in it being displayed as plain text when rendered

Currently, I am dynamically rendering a list of elements and I need to insert other elements in front of them based on key-value pairs. I want to utilize <sup></sup> tags for these elements, but they are appearing as plain text rather than sup ...

Simulating nodemailer functionality for testing purposes using Jest

I recently implemented an endpoint for users to reset their passwords. Everything was working smoothly and my tests were passing without any issues until I integrated nodemailer to send password reset emails. For testing, I am using Jest. Oddly enough, w ...

Refresh your webpage with new content and modified URLs without the need to reload using window.history.pushState

Hey everyone, I'm looking to incorporate window.history.pushState into my website, but I'm unsure of how to go about it... What I'm aiming for is to have a page dashboard.php and update the URL to dashboard.php?do=edit&who=me, while loa ...

Tips for building a dynamic view using Angular

I am working on a project where I need to dynamically generate multiple horizontal lines using data from a JSON file, similar to the example in the image below. https://i.sstatic.net/MthcU.png Here is my attempt: https://i.sstatic.net/EEy4k.png Component. ...

Preventing Page Content Overflow in Semantic-ui SideNav

I am currently working on a webpage that includes a side navigation bar. I recently started using semantic-ui and its grid system, but I'm facing an issue where the content of the page flows under the side nav and gets hidden. I have tried various sol ...

Ways to Ensure a Property of an Object Remains Synced with Another

I'm dealing with the following Object structure: { a: "123" b: "$a" } In this setup, b should always be equal to the value of a. Any suggestions on how I can achieve this using JavaScript? ...

Retrieving the initial data from a JSON array

After declaring an array called myclinicsID using var myclinicsID = new Array();, I added some data to it. When I use alert(JSON.stringify(myclinicsID)), the output is ["1","2","3","4"] However, when I try to access this array in my function and check the ...

What is the best option: using a Javascript template or exploring another

Just starting out in web development. I want to include the same menu on every page of my new website, but I don't want to manually update it in each file whenever there's a change. Is there an easy template engine for JavaScript or another sol ...

The addition of one hour to the date time format increases the total time

Currently, I am retrieving a datetime column value from a database table as 2015-03-04 21:00:00 UTC. When attempting to convert this format into a datetime picker, the following code is used: date = moment($("#event_start").val()); // date time value fro ...

An error occurred in React.js: 'TypeError: kinds.map is not a function.'

Currently, I am attempting to retrieve data from an API and store it as a 'state' within a component, specifically the Navbar component. However, when I attempt to iterate through the data received from the API using 'map', I encounter ...

Utilizing Vuex store to showcase data in component according to route

The data stored in Vuex is as follows: state: { news: [ { id: 1, title: "placeholder", text: "Lorem ipsum doloret imes", date: "20-01-2020", type: "management" }, { id: 2, title: "Revenue", text: "Lorem ipsum doloret imes", date: "20-01 ...

Using Vue JS, I am facing difficulties in integrating Vue page transitions with Inertia JS within my application

There seems to be an issue with the transition not working on the inertia page. If I add appLayout between the transition tags, it starts working, but then all content receives the transition effect. Dashboard.vue <template> <admin-layout> ...

Paste the input text into the div element

I am attempting to create a simple form with one input field and one Div element. The goal is to have the text entered in the input field displayed in the Div when a button is clicked. Despite my efforts, I have been unable to get it to work correctly. I ...

Avoiding the resizing of table headers when positioned at the top of a window

Having an issue with resizing elements on a webpage. I have dynamically generated a table from JSON data and have a function that sticks the table header to the top of the page when scrolling: var header = $("#dataheader").offset(); $(window).scroll(func ...

Get a Javascript file from Amazon S3 and run it within a Lambda function

Within S3, there exists a hello.js file that includes the following code snippet: function greet() { console.log(" From Greetings: "); } An AWS Lambda function written in NodeJS is attempting to access and execute this script. Despite having ...

Ways to create a fixed button positioned statically at the bottom of a page

Currently, I am utilizing tailwind CSS to create a webpage with Next and Back buttons for navigation. However, an issue arises when there is minimal content on the page as the button adheres to the top. For visual reference, please view the image linked be ...

What is the best method for interacting with a blocked element in Protractor?

Whenever I attempt to click a button, a popup seems to appear in front of it, causing my automation script to fail with an error message stating that the element is intercepted and not clickable. Even after scrolling down to the element with a function, th ...

Is it possible to center the image and resize it even when the window is resized?

My goal is to position an image in the center of the screen by performing some calculations. I've tried using: var wh = jQuery(window).innerHeight(); var ww = jQuery(window).innerWidth(); var fh = jQuery('.drop').innerHeight(); var fw = jQ ...

Issue with Vue 3 component not updating following vue-router invocation

I am currently working on developing a todo app using ionic-vue with vue 3. In my Lists.vue component, I have set up an overview where users can click on different lists to load tasks specific to each list. However, I am facing an issue where the same data ...