Using Vue 3, Bootstrap, and Pinia to create an innovative Global Modal experience

After creating a ModalComponent.vue file that I intend to use across different sections, I encountered an issue with closing the modal after calling my Pinia stores. The modal includes slots for the title, body, and footer, along with a standard close button that functions correctly.

My goal is to add another button next to the close button to interact with my Pinia stores. For instance, when deleting an item from a table by clicking on the trash can icon, the corresponding modal opens, displaying confirmation options like Save, Continue, or Delete.

Once I trigger the deletion of the specific item by interacting with the component's button connected to the store, I expect the item to be removed successfully (which is visually confirmed in the table underneath the backdrop) followed by automatically closing the modal. However, despite various attempts, including setting dataModal.value to false and emitting events from the Pinia store, the modal does not close as intended.

If you have any insights or suggestions on how to achieve this functionality seamlessly, please share them. Your expertise will be greatly appreciated!

To provide context, here is an excerpt from my ModalComponent.vue:


  <template>
    <!-- ModalComponent content -->
  </template>

  <script setup>
    // ModalComponent script setup
  </script>

Additionally, here is a snippet showcasing the usage of the modal component within a larger component that includes a table:


  <template>
    <!-- Component code using the modal -->
  </template>

  <script setup>
    // Component script setup
  </script>

Lastly, here is a glimpse into the implementation of my Pinia store functionality:


  // Pinia store definition

Answer №1

After spending another 16 hours grappling with the problem, I've managed to come up with a somewhat messy but functional solution. The following code demonstrates how to display and hide the Bootstrap 5 modal with transitions and the backdrop:

ModalComponent.vue:

<template>
  <div :id="id" class="modal fade" ref="myModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="myModalLabel">
            <slot name="title"></slot>
          </h5>
          <button type="button" class="btn-close" @click="hideModal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          <slot name="body"></slot>
        </div>
        <div class="modal-footer">
          <Button :content='$t("buttons.cancel")' variant="btn-danger" icon="x-lg" :circle="false" @click="hideModal" />
          <slot name="button"></slot>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { Modal } from 'bootstrap';
import Button from '@/components/Buttons/Button.vue';
import { watchEffect, onMounted, ref } from 'vue'

const props = defineProps({
  id: {
    type: String
  }
});

const modalInstance = ref(null);

const emit = defineEmits(['get-modal'])

onMounted(() => {
  modalInstance.value = new Modal(document.getElementById(props.id), {
    target: props.id,
    backdrop: "static",
  });

  emit('get-modal', modalInstance.value)
});



	function hideModal() {
  	if (modalInstance.value) {
    	modalInstance.value.hide();
  	}
}

</script>

The component that triggers the modal:

<template>

    <modal-component @get-modal="modalGetted" :id="'deleteItemmodal'">
      <template v-slot:title>
        {{ $t('ModalTitle') }}
      </template>
      <template v-slot:body>
        {{ $t('ModalBody') }}
      </template>
      <template v-slot:button>
        <Button :content='$t("buttons.delete")' variant="btn-secondary" icon="trash-fill" :circle="false" @click="onDelete" />
      </template>
    </modal-component>
    
</template>

<script setup>
import Button from '@/components/Buttons/Button.vue'
import ModalComponent from '@/components/ModalComponent'


const { isLoading, items } = storeToRefs(useItemsStore())


let modalInstance = ref(null)

function modalGetted(modal) {
  	modalInstance = modal // set the modal
}

function onShowDeleteModal(item) {
  	itemToBeDeleted = item
  	modalInstance.show() //show the modal
}


function onDelete(){
  	removeItems(itemToBeDeleted.id)
  	modalInstance.hide() // hide the modal
  	getItems();
}

</script>

Answer №2

When it comes to controlling the display of your modal, consider the following:

Ensure that dataModal.value is set to false after calling either 'removeItems' or 'getItems' within your function 'onDelete'.

If this method does not apply to your situation, you can create a ref called 'showModal' in your script and utilize 'v-show' or 'v-if' to manage the visibility of your modal effectively.

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

What is the best way to accurately establish a new name for the evolving scope

var tags_offset=[]; $scope.getRelations = function(id, ref, subRef=0){ tags_offset[ref+'-'+subRef]=0; $http.get( CONS.appHttp+ '/tags.php?ID='+id +'&ref='+ref +'&contentType='+subRe ...

The type 'Dispatch<SetStateAction<boolean>>' cannot be assigned to type 'boolean'

Currently, I am attempting to transfer a boolean value received from an onChange function to a state variable. let [toggleCheck, setToggleCheck] =useState(false);` <input type="checkbox" id={"layout_toggle"} defaultChecked={toggleCh ...

Navigating between child nodes in an HTML drop down list with multiple options and hierarchical structure

Hey there! I am looking to create a unique HTML hierarchy drop-down menu. It will have multiple levels or options, with each option having the potential for child nodes. When an option has child nodes, an arrow will appear next to it. Clicking on this ar ...

Encountering unhandled promise rejection error with email field in NextJS when using React Hook Form

I am encountering a bizarre issue where, on my form with two fields (name and email), whenever the email field is focused and onSubmit is called, I receive the following error message: content.js:1 Uncaught (in promise) Error: Something went wrong. Please ...

Setting data for child vue components in vue-test-utils: a guide

I am currently working on a FileForm.vue component:- <template> <div class="file-form"> <form @submit="submit"> <input v-model="name" type="text" placeholder="File Name" /> <button type="submit"> < ...

Struggling to align elements vertically and horizontally using Bootstrap in an HTML file

Here is the code snippet that I have written: .box { background-color: red; } .container { height: 50vh; background-color: blue; } <!DOCTYPE html> <html lang="en"> <head> ...

Exploring the new features of utilizing buttons with the onClick method in the updated nextJS version 14.1.3

"implement customer" import React, { useState } from "react"; import { FaChevronLeft, FaChevronRight } from "react-icons/fa"; export default function HeroSlider() { const images = [ "/images/homepage/home-1.jpeg&qu ...

Confirming the accuracy of multiple fields in a form

Looking for help with validating both password and email fields on a registration form. I've successfully implemented validation for passwords, but need assistance adding validation for the email section as well. Can both be validated on the same form ...

Addressing the issue of Google Charts legends overlapping

As a newcomer to Stackoverflow and Google Charts, I am encountering an issue in one of my projects that utilizes the Google Charts API. Specifically, I am trying to display two legends on the chart but they are overlapping in the preview. Despite explorin ...

Unusual display of feedback text in Bootstrap 4

When I directly copied this code snippet from Bootstrap 4: <div class="form-group has-danger"> <label class="form-control-label" for="inputDanger1">Input with danger</label> <input type="text" class="form-control form-contro ...

The Angular ternary operator can be used in conjunction with functions for optimal

Consider this scenario: I have two functions that are triggered by a button click: <button ng-click="functionOne || functionTwo()"></button> However, I want to optimize this setup so that the functions are only called if they return a value. ...

In the Show Code feature of Storybook, every element is being displayed for

My Vue 3 + Storybook setup is all running smoothly, except for a little hiccup when I click "Show Code". It seems to display everything instead of just the template. Can anyone help me figure out what's going wrong? https://i.stack.imgur.com/zzBl0.pn ...

I am trying to locate the source of the unexpected token error

Hi there! I've encountered a syntax error in my code, specifically pointing to the closing curly bracket right above the render method. The error message indicates that it's expecting a comma, but all my curly brackets seem to have opening and cl ...

The function window.open() is experiencing difficulties when trying to open a file located in a subfolder

As someone who is new to programming, please excuse any lack of knowledge on my part, but I am having trouble finding the answer to this. I am currently using window.open() to open a .php file in a popup window and passing a variable through the URL to be ...

"Must not be currently employed" when using window.open in a basic React application

Let me share a simplified version of the webapp I'm currently developing. Whenever I run into an Uncaught Error: Should not already be working. while executing the window.open(...) line in the following code snippet: const sleep = milliseconds => ...

Tips for creating JavaScript validation for the Amount input field (in the format 22.00) in an ASP.NET application

In this aspx page using ASP.NET 4.0, there is a text box where users can enter a rate. The requirement is that only numbers are allowed to be entered. For example, if the user enters 22, it should display as 22.00. If the user enters 22.5, it should displa ...

The VueJS function is not defined

Looking for a way to fetch data from graphql in my vue project and store it in a variable. The function is asynchronous and the value of rawID needs to be awaited. However, there is a possibility that it could result in undefined, causing an error in the ...

Unexpected behavior observed in ng-select when pasting search values

When attempting to update an array of strings acting as the model for an ng-select, the values do not appear correctly in the search box. https://i.sstatic.net/WqdJ6.png The values that are displaying correctly are the ones selected from the dropdown men ...

inject custom styles into a Material-UI styled component

Although I have come across similar questions, none seem to directly address my current situation. I am in the process of transitioning from MUI v4 to MUI v5 and have encountered various scenarios where a specific style is applied externally. For instance ...

Vuex 3: The State Remains Unknown

software versions: "vue": "2.4.2", "vue-router": "2.7.0", "vuex": "3.0.1" I'm working on simulating a basic login feature with two input fields that will eventually utilize JWT for authenticated logins. However, I'm encountering an issue w ...