Avoid the mounting of a Vue component using v-if while still maintaining the transition animation

Here is my code snippet demonstrating how I created a modal using Vue. The issue I am encountering revolves around maintaining the transition effects while conditionally mounting the Vue component. Upon clicking the button in the initial code block, the modal opens and then 'mounted' is logged to the console. This behavior aligns with my expectations as the modal smoothly fades in due to the appear attribute.

However, the fade out effect does not occur because of the v-if statement. I aim to sustain the transition functionalities while retaining the v-if condition, which delays the mounted and unmounted hooks.

The necessity for keeping the v-if="showModal" stems from the challenges on iOS related to modals. To counter this, I intend to set the body to position: fixed and adjust the top property within the modal components during the onMounted hook. Removing v-if="showModal" results in the modal component being mounted upon page load, which contradicts my intentions.

<script setup>
const showModal = ref(false)
</script>

<button @click="showModal = true">show modal</button>

<Teleport to=".vue-modal-target">
  <Modal :show="showModal" @close="showModal = false" v-if="showModal">
    <ContactForm />
  </Modal>
</Teleport>

In the Modal.vue file, the following code is implemented:

<script setup>
onMounted(() => {
  console.log('mounted')
})

onUnmounted(() => {
  console.log('unmounted')
})
</script>

<template>
  <Transition appear name="modal">
    <div v-if="show" class="modal-wrapper">
      <div class="modal-mask"></div>
      <div class="modal-container">
        <button class="close-btn" @click="$emit('close')" style="color: #fff;">X</button>
        <div class="modal-container__inner">
          <slot />
        </div>
      </div>
    </div>
  </Transition>
</template>

<style>
.modal-enter-from,
.modal-leave-to {
  opacity: 0;
}

.modal-enter-to,
.modal-leave-from {
  opacity: 1;
}

.modal-enter-active,
.modal-leave-active {
  transition: all 0.5s ease-in-out;
}
</style>

EDIT

I have made adjustments based on the recommendation provided in the accepted answer. Here's the updated code:

<script setup>
const showModal = ref(false)
</script>

<button @click="showModal = true">show modal</button>

<Teleport to=".vue-modal-target">
  <Modal :show="showModal" @close="showModal = false" v-if="showModal">
    <ContactForm />
  </Modal>
</Teleport>

Code snippet used in the updated Modal.vue file:

<script setup>
onMounted(() => {
  console.log('mounted')
})

onUnmounted(() => {
  console.log('unmounted')
})

const props = defineProps({
  show: Boolean
})

const showModal = ref(false)

if (props.show === true) showModal.value = true

const emit = defineEmits(['close'])

function handleClose() {
  showModal.value = false
  setTimeout(() => {
    emit('close')
  }, 500)
}
</script>

<template>
  <Transition appear name="modal">
    <div v-if="showModal" class="modal-wrapper">
      <div class="modal-mask"></div>
      <div class="modal-container">
        <button class="close-btn" @click="handleClose" style="color: #fff;">X</button>
        <div class="modal-container__inner">
          <slot />
        </div>
      </div>
    </div>
  </Transition>
</template>

<style>
.modal-enter-from,
.modal-leave-to {
  opacity: 0;
}

.modal-enter-to,
.modal-leave-from {
  opacity: 1;
}

.modal-enter-active,
.modal-leave-active {
  transition: all 0.5s ease-in-out;
}
</style>

Answer №1

It appears that the reason why the transition is not visible when closing is because the event close is being emitted upon closure, which is then detected by the parent component to handle the conditional rendering of the child component. To enable a smooth transition effect when the modal closes, it would be necessary to set the v-if="show" directive to false before proceeding with any other changes. This can be achieved by implementing a function that sets this.show = false and subsequently triggers this.$emit('close').

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 align row elements in Bootstrap?

Hey there everyone! I've been grappling with a challenge for the past few days on how to center the contents of a Bootstrap row. Let me elaborate: The row has 12 columns (as is standard in Bootstrap). However, in my design, I'm only utilizing 9 c ...

The modal box appears to be malfunctioning

I am attempting to open the abc.html file (located in the same directory) in a modal box. Here is the code I am using, however, it doesn't seem to be working. Any assistance would be greatly appreciated. <!DOCTYPE html> <html> <head ...

Is it possible to erase the text area in MarkItUp?

I'm currently facing an issue with clearing my MarkItUp editor. I've successfully managed to insert text using the $.markItUp function, but I'm struggling to clear the text box afterward. I attempted to use replaceWith: "", however, I encoun ...

Unable to define attributes of a non-existent element (specifically 'innerHTML') within a Vanilla JavaScript component

Currently, I'm developing a Vanilla JS Component and encountering a challenge with utilizing the innerHTML() function to modify the text within a specific ID in the render() HTML code. The problem at hand is the Cannot set properties of null (setting ...

What is the best method for animating a display table to none or reducing its height to

My goal is to animate a header whenever the class collapseTest is applied. After some trial and error, I have come up with the following solution: http://jsfiddle.net/robertrozas/atuyLtL0/1/. A big shoutout to @Hackerman for helping me get it to work. The ...

Trouble getting a sticky element to align with a two-column grid within a parent container

I'm looking to keep one column sticky in a two-column grid setup. My goal is to create a vertical navigation bar that's specific to a particular div within a single-page site, with a fixed horizontal navbar across the entire page. However, I&apos ...

Changing guid bytes into a string using JavaScript

Currently, I am receiving an arrayBuffer from a WebSocket connection and within that, I am able to obtain a range of byte arrays representing a Guid created in C#. I am wondering how I can convert these Guid bytes to a string in JavaScript? Guid: "FEF38A ...

Are items placed into an array passed by reference or by value?

When working with custom Objects in an Angular context, I define two objects "a" and "b" using an interface. These are created as class attributes along with an empty array of these objects. public a: CustomObj; public b: CustomObj; public array: ...

placeholder for dropdown selection in Vue.js version 2.0.0

Currently, I am in the process of developing a web application using vuejs 2.0. In order to create a straightforward select input, I employed the following code: <select v-model="age"> <option value="" disabled selected hidden>Select Age&l ...

Application utilizing Meteor to connect with external websites or applications

Hey everyone, I'm in the process of developing an application that features a directory of stores. One key requirement is that each store has a unique view created with either Flash or JavaScript. The special view components have already been develope ...

What is the best way to retrieve the "name" and "ObjectId" properties from this array of objects? (Using Mongoose and MongoDB)

When trying to access the name property, I encountered an issue where it returned undefined: Category.find() .select("-_id") .select("-__v") .then((categories) => { let creator = req.userId; console.log(categories.name) //unde ...

What could be the reason for NPM failing to work following an update?

Just two days ago, I updated NPM and now it's suddenly not working on my Windows 10 20H2 platform. Every action I take results in the same error message: C:\Users\ethan>npm internal/modules/cjs/loader.js:883 throw err; ^ Error: Canno ...

Is there a way to navigate to the next or previous image in a lightbox by using ev.target.nextElementSibling or ev.target.prevElementSibling?

I am new to the world of web development Currently, I'm facing an issue with my lightbox feature. I want to navigate between images by using ev.target.nextElementSibling and ev.target.prevElementSibling when clicking on the next/previous arrow.png ic ...

AJAX jQuery requests can flatten arrays when they are sent

The below code shows an endpoint written in Express, using the body-parser middleware. app.post("/api/poll/new",api.NewPoll); api.NewPoll = function(req,res){ if(!req.body) return res.status(400).send("MISSING BODY"); console.log(req.body,typeof(r ...

When using axios to perform a post operation, the Firestore Cloud Function sends back an undefined response to the

Hello there, I am currently facing an issue with processing payments using Firestore Cloud Function and a payment Gateway named Yoco. The payment code seems to be functioning correctly as it is returning either a success or failure object. However, the p ...

Refresh the page with user input after a button is clicked without reloading the entire page, using Python Flask

My python/flask web page accepts user input and returns it back to the user without reloading the page. Instead of using a POST request, I have implemented Ajax/JavaScript to handle user input, process it through flask in python, and display the result to ...

Tips for seamlessly incorporating WalletConnect into your decentralized app with the help of web3-react

I have been working on integrating WalletConnect into my project by referring to the documentation provided by web3-react. The configuration settings I am using for the connector are as follows: import { WalletConnectConnector } from '@web3-react/wal ...

"Effortlessly attach and send multiple images via email using Dropzone in

I am encountering an issue with uploading multiple image files and sending them via email to customers. The ajax request is throwing an error call to a member function getclientoriginalname() on array when the uploadMultiple: true, option is added to dropz ...

Leveraging Async / Awaits with Promise

Within my code, I have a specific promise chain that follows this structure: myPromise() .then(getStuffFromDb) .then(manipulateResultSet) .then(manipulateWithAsync) .then(returnStuffToCaller) An issue arises when working within the mani ...

Creating Beautiful Math Equations with LaTeX in EaselJS

Can MathJAX or a similar tool be integrated into an EaselJS DisplayObject? I am looking for alternative options. I want to render text like $$ 5 + 3 - 3 = 5 $$ on a canvas that serves as an EaselJS stage. Ideally, I hope to achieve this using the Text Cl ...