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

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>

Related

Vuejs transition javascript hook not triggering (nuxtjs)

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.

How to pass props to sibling and child component in vue

The structure of my code is like this:
So in the Product component, I am making an API call:
<template>
<button class="btn button col-2" #click="addToCart()">
Add to cart
</button>
</template>
<script>
methods:{
addToCart: function () {
let amount = this.itemsCount !== "" ? this.itemsCount : 1;
if(this.variationId != null) {
this.warningMessage = false;
cartHelper.addToCart(this.product.id, this.variationId, amount, (response) => {
this.cartItems = response.data.attributes.items;
});
} else {
this.warningMessage = true;
}
console.log(this.cartItems)
},
}
</script>
And what I am trying to do is the response (this.cartItems) should be shown in Cart component. And my Navbar component:
<template>
<nav class="navbar navbar-expand-lg shadow">
<div class="container navbar-container">
<div class="navbar navbar-profile">
<div class="dropdown">
<button class="btn dropdown-toggle" type="button" id="dropdownCart" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fa fa-fw fa-cart-arrow-down"></i>
<span></span>
</button>
<div #click="$event.stopPropagation()">
<CartBox :cartItems="cartItems"/>
</div>
</div>
</div>
</div>
</nav>
</template>
<script>
export default {
props: {
cartItems:Object
},
components: {CartBox},
}
And CartBox:
<template>
<Cart/>
</template>
<script>
import Cart from '../components/Cart'
export default {
components: {
Cart
}
}
</script>
And my Cart component:
<template>
<div
class="dropdown-menu cart"
aria-labelledby="triggerId"
>
<div class="inner-cart">
<div>
<div class="cart-items">
<div>
<a class="remove">Remove</a>
</div>
</div>
</div>
<hr/>
<div class="cart-items-total">
<span>Total:</span>
Clear Cart
</div>
<hr/>
<router-link :to="{name: 'order'}" class="btn button-secondary">Go To Cart</router-link>
</div>
</div>
</template>
<script>
export default {
computed: {
},
methods: {
}
};
</script>
I am really confused how to pass the props to sibling component and then the child component but if you could pass it to Cart component, that would really help me.
There are two approaches for your request:
1. Using props, provide and inject
This could be accomplished with Provide / inject, after passing your response to a parent. Basically, you will emit your response from your Product component to a parent, maybe like your App.vue as the prop myData, then you provide it for every child, no matter where it is nested, like this:
provide: {
providedData: this.myData
}
In any child you can now use:
inject: ['providedData']
Please note, that this data will only be available if your Product component received it. The second approach is recommended.
2. Using a store
Using a store like vuex is a bit more complex than approach 1, but it will save a lot of time in the future. You would recieve your response in your Product component, dispatch it to the store and could call the state of information from this store anywhere in your app. See further information in this documentation: Vuex | Getting Started

How get key value in vuejs in v-for directive?

i have this on vue template:
<div v-for="item in items" :key="item.id">
<!-- content -->
</div>
i want get the value of item.id and send via axios.
i dont know how bind de value from template to script section.
You can put a button with a on click handler inside the div:
<div v-for="item in items" :key="item.id">
<button #click="sendItem(item.id)">Send</button>
</div>
And define the handler in methods section:
<script>
export default {
data: ...
methods: {
sendItem: function(itemId) {
// Using axios here
}
}
}
</script>

Presentation Component in Vue2

I want to display all my forms and info pages in floating sidebox.
I don't want to copy and paste the floating sidebox html to all the places. So I want to create a component which acts as container to my forms or info pages.
This is the sample code for form.
<div class="floating-sidebox">
<div class="sidebox-header">
<div class="sidebox-center">
<h3 class="title">{{ title }}</h3>
</div>
</div>
<div class="sidebox-content">
<div class="sidebox-center">
<!-- This is the actual content. Above container code is common for all forms. -->
<vue-form-generator :schema="schema" :model="model" :options="{}"></vue-form-generator>
</div>
</div>
<div class="floating-sidebox-close" #click="cancel"></div>
</div>
<div class="floating-sidebox-overlay"></div>
In above code, I uses vue-form-generator to generate the form. The floating-sidebox elements are common for all forms and info pages. I want to abstract it by Presentational component.
How could I do it Vue2?
Define a component that wraps all your "floating-sidebox" components. You can access the "floating-sideboxes" via this.$children and use their title etc. as navigation placeholder. Since $children is an array you can easily represent the currently visible entity with and index
...
data: function() {
sideboxes: [],
currentIndex: null
},
...
mounted: function() {
this.sideboxes = this.$children;
this.currentIndex= this.$children.length > 0 ? 0 : null;
},
...
computed: {
current: function() {
return this.currentIndex ? this.sideboxes[this.currentIndex] : null;
}
}
You can then bind in the template of the wrapping view
<ul>
<li v-for="(sidebox, index) in sideboxes" #click="currentIndex = index"><!-- bind to prop like title here --></li>
</ul>
<div>
<!-- binding against current -->
</div>
JSfiddle with component https://jsfiddle.net/ptk5ostr/3/

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.