If I click on a different VueJS menu, make sure to close the current menu

When using a component menu, each item is displayed independently. However, I would like the open items to close automatically when I click on another item with the menu.

I employ a toggle functionality on click to control the opening and closing of the components which come in various styles.

I am working with Vue.js 3 and it seems that each menu operates as a standalone entity, leaving me unsure about how to proceed.

<nav role="navigation" :id="uuid">
    <div class="app-menu">
      <div class="menu-princ" @click.stop="showModal = !showModal&">

        ...

</script>

<style lang="scss" src="./style.scss" scoped></style>

Answer №1

My experience with PrimeVue led me to discover an issue where clicking a menu on one card allowed you to open the same menu on every card, despite its click-outside-to-close functionality. Usually, clicking outside an open menu should close it. I found a helpful Vue3 directive resource here: Migrating "detect click outside" custom directive from Vue 2 to Vue 3.

The problem in my case using PrimeVue seemed to be related to the logic they internally use, particularly the consistency of el.target when clicking the same button in different card components. To address this, I implemented a composable that tracks the unique id of the current open menu and added a watcher in each menu-rendering component.

./src/composables/useSingleMenu.js

import { ref } from 'vue';

const lastOpenedId = ref(null);

export const useSingleMenu = () => {
    const open = (id) => {
        lastOpenedId.value = id;
    };

    return {
        lastOpenedId,
        open,
        close,
    };
};

./src/components/SandwichCard.vue

<script setup>
import { ref, computed, watch } from 'vue';
import { useSingleMenu } from '@/composables/useSingleMenu';

const singleMenu = useSingleMenu();

const menu = ref();
const menuId = computed(() => `sandwich-options-${props.sandwich.id}`);

const toggleMenu = (event) => {
    singleMenu.open(menuId.value);
    menu.value.toggle(event);
};

watch(() => singleMenu.lastOpenedId.value, () => {
    if (singleMenu.lastOpenedId.value !== menuId.value) menu.value.hide();
});
</script>

To implement this solution, simply integrate the provided composable and perform two actions:

  1. Call
    singleMenu.open('some-unique-id-1337');
    when opening a menu
  2. Add a watcher that closes the menu whenever singleMenu.lastOpenedId.value changes, if it doesn't match the menu's id

This approach establishes a global state for tracking the currently-opened menu id. Each menu then monitors its unique id against this state, automatically closing if it doesn't match. Consequently, only one menu can be open at any given time, maintaining sync with the active menu id.

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

I am looking to identify when the focus event occurs on all HTML input elements on a page without using addEventListener or any HTML attributes

Does anyone know a way to detect the focus event on all HTML input elements on a page without using the addEventListener function or HTML attributes? I was successful in detecting click events with the following code: onclick = () => { // do somethi ...

Accessing each element within a Next.js application through a personalized hook during page load

Within my Next.js application, I have implemented a React hook that retrieves the currently authenticated user and stores it in global state. I am looking to execute this hook once on page load while making it accessible to every component within the app. ...

Issue with importing Typescript and Jquery - $ function not recognized

Currently, I am utilizing TypeScript along with jQuery in my project, however, I keep encountering the following error: Uncaught TypeError: $ is not a function Has anyone come across this issue before? The process involves compiling TypeScript to ES20 ...

Acquiring data from an API response in JSON format using JavaScript

Utilizing a parse.com API server, I have successfully established communication in JavaScript through AJAX. The output from the response is being logged into the browser console with the following code: $.ajax(settings).done(function(response) { ...

Instructions for transforming DOM information into a JSON format

I have multiple inputs within my document, as shown in the code snippet below. My goal is to create a string or JSON object using the input names and values. var arr= []; $('ul li input').each(function(){ let name = $(this).attr(' ...

Unable to send messages despite successful connection through Sockets.io

My Java Server is set up to listen for messages from an Ionic 2 Client using Sockets.io. The server can successfully send messages to the client, but I am facing issues with getting the client to send messages back to the server. For example, when the jav ...

Merging data sets with Javascript: A comprehensive guide

As a newcomer to the world of javscript, I'm faced with what seems like a simple question. I'm working with two datasets that contain a common column and I'd like to merge them together. The structure of the datasets is as follows: const da ...

Eliminating the unwanted line breaks that are automatically inserted when integrating JavaScript with HTML code

Hey everyone, I'm new to web development and could really use some assistance. I am currently working on a website that shows the weather forecast for the next four days, using SimpleWeather.js. In my JavaScript, I want to display the High & Low temp ...

Leveraging "setState" in React Native with Promises

I am facing a challenge in updating the state of a React Component with data obtained from an API call. I encountered an issue where using the setState function within the promise resulted in an error "Type Error: _this2.setState is not a function" in Reac ...

Guide on incorporating a refresh button to automatically update information from a database in MaterialUI's Datagrid

Recently diving into JavaScript, I encountered a common issue: The data for my table is sourced from a MySQL database through Axios Whenever CRUD operations are performed in the web app, the database is updated accordingly Although backend changes ...

Numerous XMLHttp requests causing JSON data to be overwritten

I am facing an issue where my JSON data is being overwritten by the result of the last XMLHttpRequest made for each country. Is there a way to prevent this from happening? Below is the code snippet in question: function getDataBetween() { for (var i = ...

Adding a Material UI Tooltip to the header name of a Material UI Datagrid - a step-by-step guide!

I've nearly completed my initial project, but the client is requesting that I include labels that appear when hovering over specific datagrid cells. Unfortunately, I haven't been able to find any solutions on Google for adding a Material UI Tool ...

The code in the head section is not running as expected

I've been exploring the possibilities of using lambda on AWS in combination with api gateway to create a contact form for a static S3 website, all inspired by this informative blog post: https://aws.amazon.com/blogs/architecture/create-dynamic-contact ...

Working with ng-model on an array with multiple dimensions

Currently, I am working on storing data in AngularJS. My table consists of various sections, rows, and columns. In each field, there is a dropdown list with the options "O", "T" or "E". My goal is to store these values in an array format: [section][row][c ...

Navigating through dynamic elements using Selenium

I'm having trouble extracting boxer information from the flashcore.com website using Selenium. The code I've written doesn't seem to be working properly. Can anyone point out where the error might be? The expectation is that Selenium should ...

How can I seamlessly combine CoffeeScript and TypeScript files within a single Node.js project?

When working on a server-side node project utilizing the standard package.json structure, what is the best way to incorporate both Coffeescript and Typescript files? It's crucial that we maintain the availability of npm install, npm test, and npm sta ...

Rendering DataTable content seamlessly from a different webpage using JavaScript without sacrificing control

Is it possible to dynamically call HTML content from Page2.html into Page1.html by utilizing DataTables (https://datatables.net/)? Page1.html <!DOCTYPE html> <html> <head> <title></title> <meta http-equiv="Content-Type" c ...

Unable to append item to document object model

Within my component, I have a snippet of code: isLoaded($event) { console.log($event); this.visible = $event; console.log(this.visible); this.onClick(); } onClick() { this.listImage = this.imageService.getImage(); let span = docu ...

Displaying elements of array in Pug template is a key task for

As a newcomer to the Jade/Pug template engine used in Express, I am faced with a challenge. I need to display the name property of each object within an associative array that is passed as a parameter to my pug template from an express route module. I hav ...

Browsers seem to only respond to the FileReader onload event on the second try

Currently I am working on implementing in-browser image processing using HTML5 and encountering a strange issue specifically in Chrome. The problem lies with the onload event handler for the File API FileReader class, as the file is only processed correctl ...