Using Vue 3 to have the ability to include multiple composable instances in a single script tag

Currently in the process of revamping our components that are originally built using the Options API. A key point for refactoring from a code-cut perspective is how we handle our multiple modals, each with their own open/close and boolean logic scattered throughout.

The challenge I'm facing is figuring out how to implement a composable function that can handle more than one instance of a modal.

For example, consider this simple scenario:

Modal.vue

<template>
  <div v-if="isOpen" @click="$emit('closeModal')"> 
    <slot></slot>
  </div>
</template>
const props = defineProps<{ isOpen: false }>();

useModal.ts

export default const useModal = () => {
  const isModalOpen = ref(false);
  const toggleModal = () => isModalOpen.value = !isModalOpen.value;

  return { isModalOpen, toggleModal }
}

To use this in a component, you would typically do something like this

Component.vue

<template>
  <button @click="toggleModal">Open Modal<button>
  <Modal :is-open="isModalOpen" @close-modal="toggleModal">Modal Content</Modal>
</template>
import useModal from "useModal";

const { isModalOpen, toggleModal } = useModal();

This approach works well when there's only one Modal present on the page. But how can we scale this to work with multiple Modals seamlessly? How can we avoid duplicating the content of the useModal composition for each individual Modal?

Ideally, we'd want to achieve something like this

<template>
  <button @click="toggleOne">Open 1</button>
  <button @click="toggleTwo">Open 2</button>

  <Modal :is-open="isOneOpen" @close-modal="toggleOne">Modal 1</Modal>
  <Modal :is-open="isTwoOpen" @close-modal="toggleTwo">Modal 2</Modal>
</template>
import useModal from "useModal";

const { isOneOpen, toggleOne } = useModal();
const { isTwoOpen, toggleTwo } = useModal();

However, this approach doesn't work as intended. Is there a way for me to achieve my goal here, or am I missing a fundamental concept regarding the usage of composables?

I've experimented with variations like the following

const { isModalOpen as isOneOpen } = useModal();

const isOneOpen = useModal().isModalOpen;

const isOneOpen = { ...useModal().isModalOpen; };

Unfortunately, none of these attempts yielded the desired outcome.

Answer №1

To change the names of the variables that are returned by the composable function, you can use object destructuring like this:

const { isOpen: modalOneOpen, toggleModal: toggleModalOne } = useModal();

This will help in distinguishing between different modals and their states.

See a live example here: https://example.com/vue-3-composition-destructuring

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

Change the color when hovering over the select box

Using jQuery, my goal is to change the hover color in a select box from its default blue to red. I understand that the hover color of the select input may vary based on the operating system rather than the browser, but I am making progress towards achievin ...

Importing the grid.js html function is necessary when incorporating formatter in Vue

Currently, I am implementing the gridjs-vue wrapper in combination with grid.js for my Vue project. My goal is to utilize the formatter feature provided by grid.js; however, it necessitates the use of the html function. Can someone please guide me on how ...

Determining age in a Class upon instance creation

Is there a way to encapsulate the age calculation function within the Member Class without resorting to global space? I want to automatically calculate and set an age when creating an instance. Currently, I have a function that works, but I'm curious ...

Ways to extract individual values from a Json Array and utilize them individually

I have a JSON data structure that I need to parse and separate each field into different arrays, so that I can use them individually. For instance, I want to split my data into two rooms: room 1 and room 2. After separating the data, I need to format it a ...

Guide on converting a unique JSON structure into a JavaScript object

I've been on the hunt for a solution to this unique format challenge, but have hit a dead end so far. The issue at hand is that I'm dealing with a JSON format that doesn't play nicely with mongoDB. My goal is to convert the JSON data into a ...

Setting a default value in react-select

Recently, I developed a react-select component that is compatible with redux-form. The SelectInput component looks like this: const MySelect = props => ( <Select {...props} value={props.input.value} onChange={value => props.input.on ...

Button missing post ajax loading

I've encountered a problem with my code that populates a table and contains buttons, which trigger an AJAX load. The content is loaded into a DIV with the ID 'DIV1', but when I try to access the buttons in that DIV1 by clicking on them, they ...

Iterating through a jQuery function to increment value

I have encountered an issue while trying to calculate the total value from an array of form fields. The problem lies in how the final value is being calculated on Keyup; it seems that only the last inputted value is being added instead of considering all t ...

Executing a function when clearing an autocomplete textfield in Material-UI

Currently, I am working with a material-ui autocomplete text field in order to filter a list. My goal is to have the list repopulate back to its original form when the user deletes the text and presses the enter key. After my research, it seems like the ...

Resetting the index and length in Vue.js each time a new page is loaded

Currently facing an unusual issue that I'm struggling to resolve. My goal was to include an index number in a for-each loop and calculate the total count of data within my vue.js component. While I successfully achieved this, I encountered a problem w ...

Using JavaScript, what is the method for inputting values into a window.prompt()?

I've been working on a project that involves scraping basic HTML pages from an internal server at my workplace. When I visit these pages, a popup window similar to a windows.prompt() appears, asking for a username and password with the message "Enter ...

``I am experiencing issues with the Ajax Loader Gif not functioning properly in both IE

I am brand new to using ajax and attempting to display a loading gif while my page loads. Interestingly, it works perfectly in Firefox, but I cannot get it to show up in Chrome or IE. I have a feeling that I am missing something simple. The code I am using ...

The jQuery each function in combination with the index function allows for

I'm struggling to make this jQuery script work properly: $(document).on('knack-scene-render.scene_126', function() { $('#view_498 > div.kn-list-content.columns.is-multiline').each(function(index) { if ($(this).eq(inde ...

Is it possible to automatically close navigation dropdowns when the screen size changes?

I am using a bootstrap 4 navbar with dropdowns that open with CSS animation/fade-in on desktop, and a separate toggle button for mobile. Everything works fine, but when I open the dropdowns on mobile and then resize the window screen, they remain open whic ...

Unable to adjust the x-axis time display in Chart.js

Within my ChartData Component, I am fetching data from an API and displaying it through a chart. The crucial aspect here is the determine Format Logic, which determines the time format of the data. My main challenge lies in changing the time display when s ...

Using both PHP and jQuery to add a class upon changing the URL

I am struggling to implement sorting functionality on my webpage, as the active class is not being added to the selected sorting option... Check out my code snippet below: <ul class="nav nav-tabs"> <li class="menusel active" name="hlavni" on ...

Converting database data into an array of objects using JavaScript

In my App.js file, I have the following code: const getPlayers = async()=>{ const players = await API.getPlayers(); setPlayers(players) } getPlayers() The following code is from my API.js file: const getPlayers = async() => { return getJson( ...

Attempting to implement an EventListener to alter the navbar upon scrolling, unsuccessful at the moment

Exploring ways to update the navigation bar upon scrolling to shrink its size and modify the color scheme (specifically, transitioning from a transparent background to white and altering font colors). Below is the HTML snippet: /* Defining the overa ...

WooCommerce Checkout and My Account Edit Address now feature dynamic selectable fields for improved customization options

After finding a solution on Stack Overflow to show sub Areas dropdown based on the selected city in WooCommerce checkout, I customized the code for my specific requirements: function cities_areas_settings() { $text_domain = 'woocommerce'; ...

Navigate Formik Fields on a Map

Material UI text-fields are being used and validated with Formik. I am looking for a way to map items to avoid repetitive typing, but encountering difficulties in doing so. return ( <div> <Formik initialValues={{ email: '&a ...