Cant get modal transition working on leave - vue.js

When im opening the modal, it transition without problems, but when hiding the modal, it doesnt transition out again - It just disappears.
I have the inside the modal (Worked in Vue2), but that seems to be a problem... If I move the component outside to the parent component and wrap the component in the transition it works, but it seems like it's not possible to have the component inside the component? Any ideas ?
See a Codesandbox here: https://codesandbox.io/s/ancient-cookies-rdm3w?file=/src/components/Modal.vue

Move the transition tag into the parent, wrapping the component. If you wrap the transition on the modal / child component itself, the component will be unmounted when you click the close modal button, and the animation won't have time to run.
<transition name="modal" :appear="true">
<Modal v-if="showModal" #close-modal="showModal = false" />
</transition>

Related

Preventing a global component getting triggered twice in vue

How do I use the same global component in a parent view and child (to the parent) in VueJs?
At the moment the global component is getting triggered twice when I trigger a function in the child component.
Parent
<ChildCompt ref="childCompt" />
<Modal ref="modalA" />
<div #click="triggerModalParent()">
Trigger Modal
</div>
Trigger function triggerModalParent: this.$refs.modalA.show();
Child
<Modal ref="modalB" />
<div #click="triggerModalChild()">
Trigger Modal
</div>
Trigger function triggerModalChild: this.$refs.modalB.show();
Try using different refs for parent and child modal imports, at the moment your imports have the same ref, hence they both get triggered

Add event on slot

I'm trying to implement generic modal component with Vue 3.
And I want to close modal window on click outside the modal's content.
So I added 'close' event on modalWrapper and 'contentClick' to prevent closing (bubbling) when content is clicked:
contentClick(event:Event){
event.stopPropagation();
}
Modal:
<template>
<teleport to="body">
<div class="modal-window" v-on:click="close" v-show="isOpened">
<slot class="modal-window__content" v-on:click="contentClick($event)"></slot>
</div>
</teleport>
</template>
The problem is that contentClick(event:Event) is not fired for some reason. I can wrap slot into another div and put contentClick event on it, but not sure that it's a good solution

Vue scoped slot child not rendering slot content

I think I've stumbled over something really strange. I have a Menu component which has two ways of managing visibility of a dropdown div:
Internally using local state;
Using v-model to keep track on the parent component.
I also have a child component called MenuItem. This MenuItem (one or more) is to be passed into the Menu default slot. The MenuItem has a slot of its own, for an icon.
The Menu also has a slot for the "activator", an element which toggles the menu visibility. This can be a regular slot, or a scoped slot.
If the visibility of the menu is handled through the scoped slot:
<Menu>
<template v-slot:activator="{ on }">
<button v-on="on" type="button">Click me</button>
</template>
</Menu>
Then the icon for MenuItem will render the first time the menu is visible, but subsequent changes to visibility won't render the icon. The icon slot is optional, so I am checking for it's presences using this.$slots['icon-left'], and after the first render this is undefined.
However, if I manage the visibility on the parent component using v-model, this behaviour is not present.
<Menu v-model="isMenuVisible">
<template v-slot:activator>
<button #click="isMenuVisible = !isMenuVisible" type="button">Click me</button>
</template>
</Menu>
I am using v-if for toggling the visibility of the dropdown menu. This behaviour is not present if I use v-show. This behaviour is also not present if I do not check for the existence of this.$slots['icon-left'].
I have a full demo of the issue.
Basically I am very confused as to why this is happening, and I don't even know what to Google.

How to reset vue modal component working with vue-show to use autofocus

I made modal component using v-show options live below.
<registerModal v-show="register.etcCompanyVisible" />
Thus, when register.etcCompanyVisible is true, this modal appears.
And this modal has some input like this.
<input type="text" v-model="etcCompanyName" placeholder="name" autofocus />
When this modal is opened at first time, the autofocus works well.
And then, this modal can be closed with cancel button by changing register.etcComapnyVisible to false.
<button class="btn secondary" v-on:click="etcCompanyVisibleClosed()">Cancel</button>
When I open modal again, the autofocus doesn't work. I think it needs some reset option for this modal, but I don't know how it can be done.
Could you give me some recommendation? Thank you so much for reading.
My understanding is that the autofocus attribute is only reliable on page load, so you need to handle the focus event yourself.
The easiest way to do this is to put a ref on your input.
<input ref="companyName" type="text" v-model="etcCompanyName" placeholder="name"/>
Then when you launch your modal, maybe you are using a button, call the focus on that $ref.
<template>
...
<button #click="focusInput">launch modal</button>
...
</template>
<script>
...
methods:{
foucusInput() {
this.$refs.companyName.focus();
}
}
Note that you could use the same method to dynamically focus inputs in a certain order. Here is a fiddle demonstrating that using button clicks but you could easily use this to move from one input to the next automatically after a certain condition is met.

Animating SPA States with Vue

So I have an active Vue.js SPA. I want to animate the transitions between each 'page'. I have the router wrapped in the transition tag like so:
<transition name="example">
<router-view></router-view>
</transition>
I then apply some css like so:
.example-enter, .example-leave-to{
opacity:0;
}
.example-leave, .example-enter-to{
opacity:1;
}
.example-enter-active, .example-leave-active{
transition: opacity 500ms;
}
What this does though, is it fades in the view, but when it exists, the new view comes up from the bottom, rather than just fading out, and fading in. So what am I missing here? Is it because I wrapped the router-view in the transition tag?
Nevermind, I figured it out. on the example-leave, example-enter-to needs to be changed to opacity 0.