Why does this Vue3 transition break data binding? - vue.js

I have this issue I've been hitting for hours now; I can't understand why it doesn't work as expected.
I pasted an example code below. The issue is that when editing the name, {{name}} is not updated. However, if I remove either of the <transition> element or the v-if="show" condition, then data binding works as expected. Same if the {{name}} is placed outside the transition.
So it seems the transition blocks data binding? However I don't find anything about it in the docs or elsewere. I tested this code in a Vue2 playground, and it works as expected (data binding works). So the behavior seems to depend on Vue3.
Is there something I'm missing? Is it a bug in Vue3?
Thanks in advance for any input or idea.
<template>
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<div v-if="show">
<p>hello, {{name}}</p>
<input v-model="name" type="text" />
</div>
</transition>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
data() {
return {
name: "",
show: true,
}
}
});
</script>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.8s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>

It works just fine in plain JS...
So try to focus on the differences:
TypeScript (i cannot use it here on SO) - I really doubt its the cause but you can try
Scoped CSS - did you tried to remove scoped ? There are some issues with scoped CSS and <transition>. Check this issue in Vue-loader. My example is not build with Webpack so Vue-loader is not used but it's for sure used in your project...
const app = Vue.createApp({
data() {
return {
name: "",
show: true,
}
},
template: `
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<div v-if="show">
<p>hello, {{name}}</p>
<input v-model="name" type="text" />
</div>
</transition>
</div>
`
}).mount("#app");
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.8s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.0/vue.global.js"></script>
<div id="app"></div>

I meet same question, you can try to set the initial value of 'show' to false and at the lifeCycle to modify 'show' for true.

Related

[Vue warn]: Unknown custom element: <cc-text-area> - did you register the component correctly?

I am making a component InputText.vue as follows:
<template>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<h4>Edit Text:</h4>
<textarea class="form-control" cols="50" rows="4" placeholder="Enter text here..." v-model="textBoxInput" #keyup="textChanged"></textarea>
</div>
</div>
</div>
</template>
<script>
export default{
data: function(){
return {
textBoxInput: ""
}
},
methods: {
textChanged: function(){
this.$emit('displayTextChanged', this.textBoxInput);
}
}
}
</script>
Then I am registering and using it in CardFront.vue component as follows:
<style>
.edit-area {
padding: 20px;
height: 800px;
background-color: #d2f9f9;
}
.card-display {
padding: 20px;
height: 800px;
}
</style>
<template>
<div class="row">
<div class="card col-sm-6 edit-area">
<cc-text-area></cc-text-area>
</div>
<div class="card col-sm-6 card-display">
</div>
</div>
</template>
<script>
import TextInput from './TextInput.vue'
export default{
components: {
ccTextArea: TextInput
}
}
<script>
It gives this error:
Error
Please help me out. I am using Vue version 2. Whenever I try to refresh the page, it gives error like: [Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I am making a component InputText.vue as follows:
Check that the filename and component names match.
If you import TextInput from './TextInput.vue' in the using component, then also make sure you name your component that, and optionally add a name property as suggested in the comments.
// TextInput.vue (not InputText.vue)
export default {
name: 'TextInput',
...
}
I solved the issue. Thank you so much everyone for your help. The issue lied in the closing script tag in CardFront.vue component.

Vue: How to trigger transitions for dynamic components instances that use the same template

I'm using Vue 3 with tailwind and I'm having trouble transitioning between dynamic components. As described in the documentation, I tried the following:
<transition
enter-active-class="duration-500 ease-out"
enter-class="translate-x-full opacity-0"
enter-to-class="translate-x-0 opacity-100"
leave-active-class="duration-500 ease-in"
leave-class="translate-x-0 opacity-100"
leave-to-class="translate-x-full opacity-0"
mode="out-in"
>
<component :is="elementFormat" :key="elementKey" />
</transition>
Where elementFormat obviously refers to the component template that should be rendered. This is a computed property from the vuex store.
Although I can see that elementFormat is updated in the console, the transition won't play, unless I wrap a v-if or v-show around it, and hide it. What am I missing?
Check if you have imported the tailwind css correctly because I have recreated your problem and it seems everything works perfectly,
const Demo = {
data() {
return {
view: 'v-a'
}
},
components: {
'v-a': {
template: '<div>Component A</div>'
},
'v-b': {
template: '<div>Component B</div>'
}
}
}
Vue.createApp(Demo).mount('#demo')
.component-fade-enter-active,
.component-fade-leave-active {
transition: opacity 0.3s ease;
}
.component-fade-enter-from,
.component-fade-leave-to {
opacity: 0;
}
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/vue#next"></script>
<div id="demo">
<h3>Vue.js Demo</h3>
<input v-model="view" type="radio" value="v-a" id="a"><label for="a">A</label>
<input v-model="view" type="radio" value="v-b" id="b"><label for="b">B</label>
<transition name="component-fade" mode="out-in">
<component :is="view"></component>
</transition>
<br>
<br>
<h3>Your Code</h3>
<transition enter-active-class="duration-500 ease-out" enter-class="translate-x-full opacity-0" enter-to-class="translate-x-0 opacity-100" leave-active-class="duration-500 ease-in" leave-class="translate-x-0 opacity-100" leave-to-class="translate-x-full opacity-0"
mode="out-in">
<component :is="view" />
</transition>
</div>

Transitions not working on nuxt-child component when route changes

I want to create a very simple nuxt transition between child routes.
The structure is:
index.vue
index
--one.vue
--two.vue
--three.vue
index.vue:
<template>
<div>
<nuxt-link to="/one">one</nuxt-link>
<nuxt-link to="/two">two</nuxt-link>
<nuxt-link to="/three">three</nuxt-link>
<nuxt-child :key="$route.fullPath"></nuxt-child>
</div>
</template>
<script>
export default {
transition: 'fade',
data(){
return {
}
},
}
</script>
<style scoped>
.fade-enter-active, .fade-leave-active{
transition: all 1s;
}
.fade-enter, .fade-leave-to{
opacity: 0;
}
.fade-leave, .fade-enter-to{
opacity: 1;
}
</style>
The child components:
one.vue:
<template>
<div>
1
</div>
</template>
two.vue
<template>
<div>
2
</div>
</template>
three.vue
<template>
<div>
3
</div>
</template>
The problem is:
that nothing happens! when I change routes, they change in a way like there is no transition.
what I have done:
I tried to do exactly what the nuxt document has said.
Also I searched a lot about it, but unfortunately, none of the similar questions have been answered.
question1
question2
question3

Vue.js - Transitions between conditionals (v-if and v-else)

Is there a way that you can use transition between vuejs conditionals v-if and v-else?
As an example:
<transition name="fade">
<p v-if="show">hello</p>
<p v-else>Goodbye</p>
</transition>
new Vue({
el: '#demo',
data: {
show: true
}
})
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s
}
.fade-enter,
.fade-leave-active {
opacity: 0
}
I can't seem to get a transition to work in such a scenario, where, as you toggle show, the <p> elements use a transition between them.
https://jsfiddle.net/fbponh78
Your problem is caused by the fact that vue transition does not see the element change, it only sees the content change.
This is caused by the fact that both elements have the same tag name, so vue just reuses this. To counteract this, give both elements an differed key value:
<p key=1 v-if="show">hello</p>
<p key=2 v-else>Goodbye</p>
Example:
new Vue({
el: '#demo',
data: {
show: true
}
});
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s
}
.fade-enter,
.fade-leave-to {
opacity: 0
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.14/dist/vue.min.js"></script>
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p key=1 v-if="show">hello</p>
<p key=2 v-else>Goodbye</p>
</transition>
</div>
Use two transitions:
new Vue({
el: '#demo',
data: {
show: true
}
})
.fade-enter-active {
transition: opacity .5s
}
.fade-enter,
.fade-leave-active {
opacity: 0
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
<transition name="fade">
<p v-if="!show">Goodbye</p>
</transition>
</div>
https://jsfiddle.net/saeedahmadi/fbponh78/10/
I had a problem, where a complex component would make v-else enter before v-if was removed. What helped me was #Khalil's (comments) suggestion:
<transition mode="out-in" ...

Vue 2 Transition not working

I have no idea where my code went wrong. It should be a simple transition. When I click the button the message shows correctly, but just that the there is no fade transition happening at all.
<template>
<div>
<transition name="fade">
<message v-show="showMessage" class="tr pop-up-message">
<p slot="header">This is Header</p>
<span slot="body">This is Body</span>
</message>
</transition>
<div v-if="!showMessage" class="block" #click.prevent="showMessage = true">
<a class="button is-primary">Primary</a>
</div>
<div v-else-if="showMessage" class="block" #click.prevent="showMessage = false">
<a class="button is-primary">Primary</a>
</div>
</div>
</template>
<script>
import message from './Message.vue'
export default {
components:{
'message': message,
},
data(){
return{
showMessage: false
}
},
}
</script>
Have you added these CSS as well:
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
opacity: 0
}
I have tried to reproduce your code here with above CSS which works.
I had two <p> tags right next to each other like below
<p v-if="!isControlling">Take control of the camera by clicking</p>
<p v-else>Press <kbd>Esc</kbd> to exit camera. <kbd>W</kbd> <kbd>A</kbd> <kbd>S</kbd> <kbd>D</kbd> <kbd>Space</kbd> <kbd>Shift</kbd> to move. Mouse to look.</p>
and they just didn't work. It looked like Vue was reusing the same <p> tag in the markup to render both. Adding a key to each made the transition work (thanks #Mark). The fix should look something like below
<p key="asd" v-if="!isControlling">Take control of the camera by clicking</p>
<p key="asf" v-else>Press <kbd>Esc</kbd> to exit camera. <kbd>W</kbd> <kbd>A</kbd> <kbd>S</kbd> <kbd>D</kbd> <kbd>Space</kbd> <kbd>Shift</kbd> to move. Mouse to look.</p>