Vuejs transition javascript hook not triggering (nuxtjs) - vue.js

I'm trying to add some animations to my vuejs(v2)+nuxt site using GSAP. To do that I need to trigger some animations on scroll. Vue provides some handy javascript hooks for it but they seem to not be working in my case.
<template>
<div class="container-xxl">
<div class="row">
<div class="col-12">
<div class="text-center">
<transition #before-enter="beforeEnter" #enter="enter" #leave="leave">
<h1>Test Component</h1>
</transition>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'TestComponent',
methods: {
beforeEnter (el) {
console.log('before enter')
},
enter (el, done) {
console.log('enter')
},
leave (el, done) {
console.log('leave')
}
}
}
</script>

When using JavaScript-only transitions, the done callbacks are required for the enter and leave hooks. Otherwise, the hooks will be called synchronously and the transition will finish immediately.

Related

Vue - display/create component from a function

One thing that I have been struggling to figure out how to do better is modals. Currently, I am registering the modal component on each Vue that needs it. However, this feels rather sloppy, as I am having to register the component several times. Even using mix-ins just does not feel like an elegant solution. What would be optimal to be able to do is to mimic JavaScript's alert() method on the Vue instance. For example, be able to call this.ShowModal(Header, Body)
However, from my understanding, there is no way to accomplish this
Take for example my Modal example. You could have a modal template like this:
<script type="text/x-template" id="modal-template">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot>
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" #click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</script>
Then you would have to reference the component over and over again like this
<template>
<button #click="displayModal">Display the Modal Alert</button>
<modal v-if="showModal" #close="showModal = false">
<h3 slot="header"> This is a good header </h3>
<p>
Look at me I am the body! You have seen me {{displayCount}} times!
</p>
</modal>
</template>
<script>
components: {modal},
data: {
showModal: false,
displayCount: 0
},
methods: {
displayModal(){
this.displayCount++
this.showModal = true;
}
}
</script>
If you wanted to reuse the component for several messages from within the parent you would then have to add several more variables to store things such as the header and body. You could put some of the logic into a mixin but you would still have to have the clutter of adding the modal component and possibly the mixin.
This brings us to the question. Is there a way to create a function in the Vue instance that would allow for us to dynamically create a Modal component and fill in the slots with arguments passed to the function? e.g. this.ShowModal("This is a good header", "Look at me I am the body!")
Use Vue.extend() create a "modal" constructor and create a instance,you can mount it to DOM dynamically by $mount or other ways
In Modal example:
modal.vue:
<template>
<div>
{{message}} //your modal content
</div>
</template>
<script>
export default {
name: 'modal',
data(){
return {
message: '',
}
},
methods:{
/************/
close () {
/****this.$destroy()****/
}
}
}
</script>
modal.js:
import myModal from 'modal.vue'
import Vue from 'vue'
const modalConstructor = Vue.extend(myModal)
const modal = (options,DOM)=>{
const modalInstance = new modalConstructor({data:options})
modalInstance.vm = modalInstance.$mount() //get vm
const dom = DOM || document.body // default DOM is body
dom.appendChild(modalInstance.vm.$el) // mount to DOM
return modalInstance.vm
}
export default modal
now you can create a Modal component by a function like this:
import showModal from 'modal.js'
showModal({message:"..."})

How to trigger Bootstrap-vue modal on page load without button or link?

Sorry for the help request, but I can't work out how to get a bootstrap-vue modal to display initially on page load without needing to trigger it with a button or link.
Thanks.
Instead of trying to open modal on page load, you can open it on mounted event of Vue.
Elevated from sample code on Bootstrap-Vue website:
<template>
<div>
<b-modal ref="my-modal" hide-footer title="Using Component Methods">
<div class="d-block text-center">
<h3>Hello From My Modal!</h3>
</div>
<b-button class="mt-3" variant="outline-danger" block #click="hideModal">Close Me</b-button>
<b-button class="mt-2" variant="outline-warning" block #click="toggleModal">Toggle Me</b-button>
</b-modal>
</div>
</template>
<script>
export default {
methods: {
showModal() {
this.$refs['my-modal'].show()
},
hideModal() {
this.$refs['my-modal'].hide()
}
},
mounted() {
this.showModal();
}
}
</script>

#click in vue component is not fired

I'm struggling with vue event listner.
I can fire the mounted() method.
But I can't fire the on click method.
this is my vue component.
Could you help me??
Layout.vue
<template>
<div id="layout">
<div class="button">
<button #click="update">update1</button>
<button #click.native="update">update2</button>
</div>
</div>
</template>
<script>
export default {
mounted() {
alert("") //fired
},
methods: {
update() {
alert("") //not fired both of the buttons
},
},
}
</script>
======additional information=============
app.js
Vue.component('vue-layout', require('./views/Layout.vue').default);
html
<body>
<div id="app">
<vue-layout></vue-layout>
</div>
<script src="/js/app.js"></script>
</body>

How to perform a transition on a simply component load with Vue.js

This is what the Vue.js documentation state:
Vue provides a transition wrapper component, allowing you to add
entering/leaving transitions for any element or component in the
following contexts:
Conditional rendering (using v-if)
Conditional display (using
v-show)
Dynamic components
Component root nodes
I just simply have a component that is loaded and filled out with XHR data though. How do I go about using a transition to show when the elements v-for gets the data array from an ajax request and builds up my template?
I want a nice fade in instead of simply "plopping" the data into the dom. and have it show up with a delay out of nowhere.
My components example:
https://jsfiddle.net/uwk1x1bx/
<template>
<transition name="fade">
<div class="row">
<div class="col-md-12" v-for="faq in faqs">
<h2>{{ faq.description }}</h2>
<div v-for="item in faq.items" class="panel panel-default">
<div class="panel-heading">{{ item.description }}</div>
<div class="panel-body" v-html="item.answer"></div>
</div><!-- /.panel -->
</div><!-- /.col-md-12 -->
</div><!-- /.row -->
</transition>
</template>
JS
<script>
export default {
name: "Faq",
data() {
return {
faqs: []
}
},
created() {
this.fetchFaqData();
},
methods: {
fetchFaqData() {
Vue.http.get('/services/getfaq').then((response) => {
this.faqs = response.data;
}, (response) => {
console.log(response);
})
}
}
}
</script>

Vue JS Component reattach or Cache

VueJS component doesn't get cached or atleast reattached after navigation. On refresh or launch everything gets attached and rendered well but after navigating to another page then back. The First Component - Carousel - component in my case doesn't get rendered but the API call is made.
<template>
<div class="rel">
<div id="homeCarousel" class="owl-carousel owl-slider">
<div class="item" v-for="product in featured">
<div class="bg-holder top-area-half" >
<div class="bg-mask-lighten"></div>
<img class="bg-img" v-bind:src="product.feature_image_url">
<div class="hero-caption">
<div class="container">
<h3 class="hero-title">{{product.feature_title}}</h3>
<p class="hero-subtitle">{{product.feature_subtitle}}</p>
<a class="btn btn-white btn-ghost btn-lg hero-btn" href="#">Shop now</a>
</div>
</div>
</div>
</div>
</div>
<div id="hero-slider-nav" class="hero-slider-nav">
<div class="container">
<div class="pull-right"></div>
</div>
</div>
</div>
</template>
<style>
</style>
<script>
export default{
data(){
return{
featured:[]
}
},
ready(){
},
mounted(){
this.getFeaturedProducts();
},
components:{
},
methods: {
getFeaturedProducts: function () {
Vue.http.get('/api/product/filter/featured=1').then(
(response) => {
this.featured = response.body;
}
)
}
}
}
</script>
`
<template>
<div class="global-wrapper clearfix ">
<keep-alive>
<Carousel></Carousel>
</keep-alive>
//The rest of the code which is just importing the Component
I found out what i was doing wrong. I had a separate JS/JQuery file and on the document ready i was initializing an owl carousel by id #('homeCarousel').owlCarousel({}) . What worked was, since i had already bootstrapped owl carousel -> on the mounted lifecycle callback i was now targeting the element and making it an owl carousel.