Vue.js: how to make transition-group to trigger only once? - vue.js

I have this Vue transition-group below. It works properly, but the problem is, when any element in the loop updates (hash changes, which is used for key), the transition group triggers the animation for that updated element (every time it updates).
I need it to only animate the elements once, when they are added to the items array (the elements are added with items.unshift(newItem))
<transition name="notification-transition">
<custom-component
v-for="item in items"
:key="'item-' + item.hash"
></custom-component>
</transition>
.notification-transition-enter-active {
transition: all 0.5s ease;
}
.notification-transition-leave-active {
transition: all 0s ease;
}
.notification-transition-enter,
.notification-transition-leave-to {
opacity: 0;
transform: translateX(256px);
}
Vue docs mention that it runs "when items are inserted, updated, or removed from the DOM" but doesn't say anything about how to limit it to just the inserted and removed event.

I found the problem. It re-triggers transition because the property item.hash, which is used for key, changes. I have to use some static key property, that doesn't change
<transition name="notification-transition">
<custom-component
v-for="item in items"
:key="'item-' + item.staticHash"
></custom-component>
</transition>

Related

Using v-model inside nested v-for

I am trying to use multiple carousel components inside card components with nested v-for loops but I’m having trouble figuring out the correct way to assign the carousel v-model so that it’s unique and doesn’t update all the carousels when the slide is changed which is what I currently have,
Here is the code I have so far:
<q-card
v-for="(item, index) in inventory"
:key="index"
style="width: 20rem;"
>
<q-card-section
class="q-pa-none text-white"
>
<q-carousel
animated
arrows
navigation
infinite
style="height: 15rem;"
v-model="slide" // What should this be assigned so that
>
<q-carousel-slide
v-for="(image, index) in item.images"
:key="index"
:name="index" //It works with the slide name and only updates the respective q-carousel
:img-src="image.url"
>
</q-carousel-slide>
</q-carousel>
</q-card-section>
</q-card>
slide is simply a data prop assigned to 0, this works but when I change the slide of one carousel all of the carousels change too.
Hopefully this makes sense, It’s a bit hard for me to explain it but let me know anything that needs clarification
Edit: Dropped the code in codepen here is the link: https://codepen.io/launchit-studio/pen/jOVrKzQ
The issue I am having is that the v-model affects all of the carousel slides not just the one that is clicked. I understand this is because the slide prop is shared by all the carousels but I am not sure of what to use in order for it to be 'independent'
Instead of using a single model slide for all the slides, use an array of models. (An object would work too).
data() {
return {
slide: 1, ❌
activeSlides: [] ✅
}
}
The index of the carousel in the v-for will also be used as the index in the array:
<q-carousel
animated
arrows
navigation
infinite
style="height: 15rem;"
v-model="activeSlides[index]"
>
Since each carousel's model needs to start at 1, you can initialize activeSlides accordingly:
created() {
const numCarousels = this.inventory.length;
this.activeSlides = Array(numCarousels).fill(1);
},
Here is the updated CodePen.

Carousel via Vue (how use transition?)

I beginner for Vue, and I trying make carousel via Vue.
I have the code: https://jsfiddle.net/z3m76w5r/4/ (example)
<style>
.switch-enter-active,
.switch-leave-active {
transition: all .5s ease-in-out;
}
.switch-enter {
left: 100%;
}
.switch-leave,
.switch-leave-to {
left: -100%;
}
</style>
<div id="banner">
<transition name="switch">
<banner class="content" v-bind:slide="currentSlide"></banner>
</transition>
<div>
I want animated my carousel. But my transition-vue don't work, despite I looked at the docs and manuals.
Reason why your transition using Vue build-in <transition> component doesn't work is because its designed to work when some element/component is entering or leaving the DOM in context of:
Conditional rendering (using v-if)
Conditional display (using v-show)
Dynamic components
Component root nodes
Your image element is not entering or leaving DOM. Its just there and you are changing it's attributes (like url etc. - which cannot be animated in any way).
For your transition to work you need at least 2 img tags to exist in the DOM during the transition - one that is leaving the DOM and one that is entering the DOM. Easiest way to do this is by using v-for with key and transition-group instead of just transition. You just change the index of image, v-for will create new img element, apply "enter" transition to it and "leave" transition to old img element (for previous index)
You can find great example of that here

Trouble animating Menu component

I am having trouble animating the menu component, which is expected to slide in and out on click, while the background fades in and out. I have in and out classes, depending on a 'showMenu' Boolean. In the sandbox, the menu flies in and out instantly when I click the Vue logo, but in my local version, everything works when they slide/fade in, but nothing happens when the menu closes. I am using the Bootstrap modal for this.
https://codesandbox.io/s/nk2xnz2wp0
As another user said, vue transitions are designed for this. You're code appeared to be overly complicated, I would advise against passing a function as a property. Vue has very good documentation about communication between child and parent components, I think maybe this is where your issues were arising from. I have modified your code to include a very basic vue transition and the menu now fades in and out, see https://codesandbox.io/s/0m13wz25pl?fontsize=14.
For possible future readers, the main code involved is:
<template>
<transition name="fade">
<HelloWorld v-on:click="showMenu = !showMenu;" v-if="showMenu" />
</transition>
</tempalte>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 2s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
</style>
Inside App I made a separate div for the background and did a separate Vue transition for menu and the background div like so:
<transition name="slide-menu" mode="in-out">
<MenuDrawer v-if="showMenu" :toggleMenu="toggleMenu" />
</transition>
<transition name="fade" mode="in-out">
<div class="darkBg" v-if="showMenu"></div>
</transition>
It definitely feels dirty, and I hope someone can show me a better solution.

disable a transition when changing page

With Vue.js, when I delete a reply, I use a "transition-group" to fadeout the reply.
However, if I'm changing the reply page, I also see the fadeout.
How can I disable the fadeout of replies when I change the replies page ?
<transition-group name="list" tag="div">
<div v-for="(reply, index) in items" :key="reply.id">
<reply :data="reply" #deleted="remove(index)"></reply>
</div>
</transition-group>
<paginator :dataSet="dataSet" #updated="fetch"></paginator>
css :
.list-enter, .list-leave-to {
transition: all 0.5s;
opacity: 0;
}
Make the <transition-group> name="list" a property that reacts to data with :name="animToUse"
Put animToUse as a property on data
Change animToUse to a non transition whenever you don't want the transition
If you are using vue-router see it's docs about transitions: Route-Based Dynamic Transition

Vue 2: Transition not working on component

I have an animation that works on other components but does not work with this one. I tried <transition-group> with no luck as well. The row simply disappears without any animation.
<transition name="card-animation">
<tr is="employee-row"
v-for="employee in employees"
:employee="employee"
:selectedOffice='selectedOffice'
:new_hire_location_options="new_hire_location_options"
v-on:fire='fireEmployee(employee)'
v-if="(employee.location.name == selectedOffice || selectedOffice == 'show all')">
</tr>
</transition>
Here's the CSS
.card-animation-enter-active, .card-animation-leave-active {
transition: transform 0.25s ease-out, opacity 0.25s ease-out;
}
.card-animation-enter, .card-animation-leave-to {
transform: scale(0);
opacity: 0;
}
What is wrong with my code?
You need to use transition-group to work with v-for. If you are using a string template, you also need the tag="tbody" attribute.
If you are using a DOM template, you need to use <tbody name="card-animation" is="transition-group">. Reference: https://github.com/vuejs/vue/issues/3907
example:
https://jsfiddle.net/2LLkene5/