Vue v-if destroys scrollbar plugin - vue.js

I try to use custom scrollbar using vuebar on dynamic Vue elements. Since v-if destroys and recreates elements, vuebar is not activated after that. On example provided you can see scrollbar works till you change tabs. I know you can use v-show and it starts working, but that solution is impossible to implement in nested components with complicated relations.
<div class="vuebar-element" v-bar v-if="tab==0">
<div>
tab 0
</div>
</div>
<div class="vuebar-element" v-bar v-if="tab==1">
<div>
tab 1
</div>
</div>
http://jsfiddle.net/ebwdnqfs/2/

After reading comment from #ssc-hrep3 I discovered that putting whole thing into
< transition > tag magically solves the problem.
<transition>
<div class="vuebar-element" v-bar v-if="tab==0">
<div>
tab 0
</div>
</div>
<div class="vuebar-element" v-bar v-if="tab==1">
<div>
tab 1
</div>
</div>
</transition>

Related

VueJS transition on computed values

I want to animate a block with posts that can be filtered.
Some filters trigger a computed method filteredPosts and they are assigned to a component liek that <block-article :posts="filteredPosts" />
In my <block-article> component I have something like that :
<template>
<div class="posts">
<div v-for="post in posts" :key="post.id"></div>
</div>
</template>
I want div .posts animate like a translation bottom/fade out on disappear and translation top/ fade in on appear.
I tried that :
<template>
<transition name="slide-fade">
<div class="posts">
<div v-for="post in posts" :key="post.id"></div>
</div>
</transition>
</template>
with corresponding css classes but it doesn't work.
I tried that :
<template>
<div class="posts">
<transition-group name="slide-fade">
<div v-for="post in posts" :key="post.id"></div>
</transition-group>
</div>
</template>
but my class .posts is a grid and here I lost the grid behavior.
THE AIM is to animate the entire div .posts rather than each elements of the v-for.
Any idea ?
Thanks all,
I finally achieve this with :
<transition name="slide-fade">
<div :key="posts.length" class="posts"></div>
</transition>
Nothe the :key="posts.length"
The problem is when posts.length doesn't change but it works in a lots of case. I will search how to fix this exception.
If you animate entire div, you should use transition, but in this case all inner elements not animated. If you want to animate all inner elements. You should use transition-group
In your case I think, need use all this method with build-in tag attribute.
Becouse in dock you can read
https://v2.vuejs.org/v2/guide/transitions.html
Unlike transition, it renders an actual element: a span by default. You can change the element that’s rendered with the tag attribute.
So you can write like this(its not full code, you must add name, key and other attrs)
<transition>
<transition-group tag="div" class="posts">
<div v-for="post in posts"></div>
</transition-group>
</transition>

how to make modal movable from one end to other end using vue js

Have code like this in vue.js ,my agenda is to make the modal movable from one end to other end, here is my code,have used bootstrap modal for this purpose and have included : draggable
<b-modal ref="my-modal" hide-footer title="Edit Record">
<div class="card">
<div class="card-header d-flex justify-content-between">
<div class="">Viz Attributes</div>
</div>
<div class="card-body">
</div>
</div>
</b-modal>
you can't position them absolutely in the viewport.
You would need to change the positioning of the modal dialog sub-container to absolute and control the left/top position based on dragging. This is not an overly easy task. You would need to create your own modal to draggable.
I suggest to you use Vue.js modal component DEMO: www.vue-js-modal.yev.io
install: www.npmjs.com/package/vue-js-modal
<modal name="bar" draggable=".window-header">
<div class="window-header">DRAG ME HERE</div>
<div>
Hello!
</div>
</modal>
Draggable property can accept not only Boolean but also String parameters.

Vue Transition inside the div element doesn't work

Could someone explain me, why the following code doesn't work?
<template>
<div class="modal">
<transition name="slide-in">
<div #click.stop class="modal__container">
<div #click="close" class="modal__button">
<span class="modal__button--close">Close</span>
</div>
</div>
</transition>
<transition name="fade-in">
<div #click="close" class="modal__overlay"/>
</transition>
</div>
</template>
I'm trying to create modal with two different animations (slide-in for text area and fade-in for modal overlay).
If i delete the element with class modal and edit code to the following everything works fine.
<template>
<transition name="slide-in">
<div #click.stop class="modal__container">
<div #click="close" class="modal__button">
<span class="modal__button--close">Close</span>
</div>
</div>
</transition>
</template>
Referencing Vue.js documentation on transitions
Vue provides a variety of ways to apply transition effects when items are inserted, updated, or removed from the DOM
That means that DOM nodes that transition applies classes to, should be those which are inserted/updated/removed.
Since it is a modal window, I assume that it has v-if directive applied in parent component to handle it's visibility. In order for transition to work, it should wrap DOM element that will be updated.
You can understand it more easily if you move code of your modal window into the parent component. Just for better visualization of elements tree and transition's behavior.
In first example, conditional rendering (v-if) applies to <div class="modal">, which is not wrapped with transition - therefore no animation will be triggered. At the same time, nested nodes are wrapped with transition, but there is nothing that will update or remove them. They are statically displayed and inserted initially on component's creation. Nothing to animate.
In order for it to work as expected following structure would be advisable:
<template>
<transition name="fade-in">
<div
class="modal__overlay"
#click="close"
>
<transition name="slide-in">
<div
v-if="containerVisible"
class="modal__container"
#click.stop
>
<div #click="close" class="modal__button">
<span class="modal__button--close">Close</span>
</div>
</div>
</transition>
</div>
</transition>
</template>
This solution expects modal__overlay to have position: fixed; style and variable containerVisible to be set to true inside mounted hook of modal component.

preventing Vue from aggresively reusing dom-elements

Condider the following snippet:
<template v-if="tryIsMobile" >
<div class='device device-mobile-portrait' :class="deviceClass">
<div class="device-scroller-container">
<div class='device-scroller'>
<img id='tryit-img-mobile' :src="srcUrlMobile" v-on:load="onImgLoad" v-on:error="onImgError"/>
</div>
</div>
</div>
</template>
<template v-else>
<div class='device device-tablet-landscape' :class="deviceClass" >
<div class="device-scroller-container">
<div class='device-scroller'>
<img id='tryit-img-tablet' :src="srcUrlTablet" v-on:load="onImgLoad" v-on:error="onImgError"/>
</div>
</div>
</div>
</template>
This code conditionally renders one of the two images. Some user action results in the actual shown image to be toggled.
What I'm seeing is the following: When toggling from say, tryit-img-mobile to tryit-img-tablet, the image loaded as part of tryit-img-mobile will get displayed with different dimensions instantly. However, during the time the image loads it's new source :src="srcUrlTablet", the image with src :src="srcUrlMobile" still displays.
This is probably due to Vue using the same img-tag for both the templates. How can I prevent Vue from doing this, and instead use seperate img-tags?
In cases such as this, Vue uses a special key attribute that tells it not to reuse the same element. Give each element this attribute with a unique value, and Vue will no longer reuse the same element:
<div v-if="tryIsMobile"
class="device device-mobile-portrait"
:class="deviceClass"
key="mobile"
>
...
</div>
<div v-else
class="device device-tablet-landscape"
:class="deviceClass"
key="tablet"
>
...
</div>

Vue named slots do not work when wrapped

I have a responsive-menu component which I want to use named slots inside of this up my template markup:
<template>
<div class="responsive-menu">
<div class="menu-header">
<slot name="header"></slot>
</div>
</div>
</template>
Whenever I try my named slot like this it work perfectly fine:
<responsive-menu>
<h3 slot="header">Responsive menu header</h3>
</responsive-menu>
However as soon as I wrap it with a class nothing shows up anymore.
<responsive-menu>
<div class="container">
<h3 slot="header">Responsive menu header</h3>
</div>
</responsive-menu>
What is going on here? Shouldn't I just be able to wrap the named component? Which does it appear that my named slots need to be direct children of my Vue component?
It does not work because your "wrapped slot" isn't direct child of responsive-menu tag.
try something like that:
<responsive-menu>
<div class="container" slot="header">
<h3>Responsive menu header</h3>
</div>
</responsive-menu>
jsfiddle
It works with Vue >= 2.6. Just upgrade vue and vue-template-compiler.