How to run a js code after vuejs render html changes - vuejs2

I am using a jquery date picker tool. But it is inside a v-if. When I toggle it on and off if I write this code it does not work.
showdatepicker:function(){
this.datepicker= true;
$(".jquery-date-picker").datepicker();
}
Because when $(".jquery-date-picker").datepicker(); runs vue still did not rendered html and added my datepicker input. But if change it to:
showdatepicker:function(){
this.datepicker= true;
setTimeout(function(){$(".jquery-date-picker").datepicker();},0);
}
It works. Because runs it after html render.
My question: is setTimeout a guaranteed way to do it after html render. Is there a proposed way in vuejs to do this right. I couldn't find any answer from my google and stackoverflow searches.

You can use nextTick which will call a function after the next DOM update cycle.
this.datepicker = true;
Vue.nextTick(function () {
$(".jquery-date-picker").datepicker();
})
And here is it's page in the documentation VueJS Docs

Vue features triggers, in your case the mounted() function could be used. This articles describes how to use it and the whole Vue hook timeline : https://alligator.io/vuejs/component-lifecycle/
A stackoverflow explanation : Vue JS mounted()

Related

How do I know if filepond is rendered?

I need to manipulate some DOM properties manually (change the style of a file element dynamically). I search for the desired element by document.getElementById ("filepond - item-" + id).
But I run into a problem if the Filepond DOM elements with initial files have not been rendered yet (getElementById() does not find any element).
I am currently solving this problem with this.$NextTick():
<template>
<file-pond
ref="filepond"
:server="server"
:files="files"
#initfile.once="markMainImage"
/>
</template>
<script>
[...]
methods: {
async markMainImage () {
await this. $ nextTick ();
document.getElementById ("filepond - item-" + id).classList.add ("main-image");
},
},
</script>
But this is not convenient and not very reliable.
Can the FilePond:loaded event be used for this purpose (https://pqina.nl/filepond/docs/api/instance/events/#filepond-loaded-event)?
If so, how do you use it in Vue?
#loaded="markMainImage" doesn't fire
Or is there another way to find out if filepond is rendered with initial files?
Thanks to Rik for comment
#addfile.once="markMainImage"
It works.

Swiper.js bugged: It knows that there are multiples slides but it doesn't let you navigate through them

I have some data coming from an API and I'm putting these data inside a slider using SwiperJS.
take a look at the code here:
As shown in the picture above. Whenever I navigate to web development/software development/UI design I load new data. The problem is, whenever I navigate to get the data, and loop through and display the data using swiper, swiper only shows me the first slide. Note that when I inspected the page I found all the slides there but the swiper for some reason is not displaying them.
here's the code:
I found the answer to my question. I had to create a function to force the rerendering of the swiper component. Here's the code:
forceRerenderSwiper() {
// Remove my-component from the DOM
this.renderComponent = false;
// If you like promises better you can
// also use nextTick this way
this.$nextTick().then(() => {
// Add the component back in
this.renderComponent = true;
});
}
then you just add an if statement when you call the component
and don't forget to set the renderComponent to true when you're ready to render it.

Changing #click event to occur on page load instead in Vue

I have some v-if props and currently to show divs with #click="tada = !tada". Instead, I would like the same divs that I'm currently triggering with the #click, to appear when the page finishes loading and occur only once.
I have tried onload, load and other things to know avail. Thanks for any help
EDIT:
I suspected it had to do with mounted but wasn't sure, so thank you for the hint.
Answer:
mounted: function () {
this.tada = true
},
You should use the mounted lifecycle hook in your main vue instance. This function is called when the component is rendered to the document for the first time. You can read more here.

How to close collapse on clicking on a button using vuejs and quasar?

I'm using <q-collapsible> tag for a collapse action. That is working fine. But I need to close the collapse by clicking some other button through Vue js only.
Since I'm using quasar it has some functionalities like open() and close() and I don't know how to implement it. So if possible someone helps me how to proceed.
This can be done easily since quasar provides this functionality out of the box.
First, reference your quasar component
<q-collapsible ref="myCollapsible">
...
</q-collapsible>
<button #click="toggleCollapsible">toggle collapsible</button>
Then, execute the needed method
methods: {
toggleCollapsible () {
this.$refs.myCollapsible.toggle()
}
}
This is for toggle, you can do the same with open and close.

Lazy loading images in Vue/Laravel

I am trying to use jQuery Lazy Loading in my Laravel/Vue project but I am struggling to get an image to appear in my Vue component. I have the following img block which I thought would work:
<img v-if="vehicle.photo_path != null" :data-original="'/storage/vehicles/' + vehicle.photo_path" class="lazy" height="180" width="150"/>
I did find this other question on here - Static image src in Vue.js template - however when I try that method I get this: Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead.
So I switched back to the v-bind method but all I am getting is a white box with a grey border - no image. If I v-bind on the src attribute however I can see the image correctly.
I know I have implemented the Lazy Loading plugin correctly as I can successfully call it elsewhere on my site (such as on a blade view), but I'm not sure where I am going wrong. Thank you.
Try moving the call to $("img.lazy").lazyload() into the mounted() method on your Vue instance. I just had a similar issue with Vue and jQuery Lazyload and that solved it for me. For example:
var app = new Vue({
el: ...
data() ...
computed: ...
methods: ...
mounted() {
$("img.lazy").lazyload()
}
})
I found many modules on the internet, but I like to avoid modules when I can. So I came up with something else, I don't know if it's the best, but it works and I didn't see any performances loss, I lazy load all the images when the page loads. You may prefer on scroll if you have lots of them, but I guess you'll figure this out if my answer fits your needs.
You'll need vueX for this, but I'll avoid the set up as this is not replying to your question.
If, like me, you have some kind of Index.vue component which main usage is to initiate all the child components (I use to do that for vue-router for instance), place a mounted() function in it :
mounted(){
const ctx = this;
// You could use this method, but if you reload the page, the cache of the browser won't allow your JS to trigger .onload method, so better use what's after.
/*window.onload = function(){
console.log('page loaded, can load images');
ctx.$store.dispatch('setPageLoaded', true);
}*/
let interval = setInterval(function() {
if(document.readyState === 'complete') {
clearInterval(interval);
ctx.$store.dispatch('setPageLoaded', true);
}
}, 100);
}
=> On the page load, I just set a page_load variable in the store to true.
Then, in any component you'd like to lazy load the image, just use 2 computeds (I used a mixin that I include in my components so I avoid repeating some code) :
computed: {
page_loaded(){
return this.$store.getters.getPageLoaded;
},
image(){
if(this.page_loaded){
console.log('starting loading image');
if(this.product.picture){
return resizedPicture(this.product.picture, this.width, this.height);
}else if(this.product.hasOwnProperty('additional_pictures') && this.product.additional_pictures.length){
return resizedPicture(this.product.additional_pictures[0], this.width, this.height);
}
return '';
}
}
}
page_loaded() goal is to return the store page_loaded variable I talk about.
image() goal is to actually load the image.
I used that for inline CSS background-image property, so my HTML looks like this :
<span v-if="page_loaded" class="image" :style="'background-image:url('+image+')'" :width="1200" :height="900"></span>
I hope it'll help, but as I said, feel free guys to tell me if it's not optimized.