Using v-model inside nested v-for - vue.js

I am trying to use multiple carousel components inside card components with nested v-for loops but I’m having trouble figuring out the correct way to assign the carousel v-model so that it’s unique and doesn’t update all the carousels when the slide is changed which is what I currently have,
Here is the code I have so far:
<q-card
v-for="(item, index) in inventory"
:key="index"
style="width: 20rem;"
>
<q-card-section
class="q-pa-none text-white"
>
<q-carousel
animated
arrows
navigation
infinite
style="height: 15rem;"
v-model="slide" // What should this be assigned so that
>
<q-carousel-slide
v-for="(image, index) in item.images"
:key="index"
:name="index" //It works with the slide name and only updates the respective q-carousel
:img-src="image.url"
>
</q-carousel-slide>
</q-carousel>
</q-card-section>
</q-card>
slide is simply a data prop assigned to 0, this works but when I change the slide of one carousel all of the carousels change too.
Hopefully this makes sense, It’s a bit hard for me to explain it but let me know anything that needs clarification
Edit: Dropped the code in codepen here is the link: https://codepen.io/launchit-studio/pen/jOVrKzQ
The issue I am having is that the v-model affects all of the carousel slides not just the one that is clicked. I understand this is because the slide prop is shared by all the carousels but I am not sure of what to use in order for it to be 'independent'

Instead of using a single model slide for all the slides, use an array of models. (An object would work too).
data() {
return {
slide: 1, ❌
activeSlides: [] ✅
}
}
The index of the carousel in the v-for will also be used as the index in the array:
<q-carousel
animated
arrows
navigation
infinite
style="height: 15rem;"
v-model="activeSlides[index]"
>
Since each carousel's model needs to start at 1, you can initialize activeSlides accordingly:
created() {
const numCarousels = this.inventory.length;
this.activeSlides = Array(numCarousels).fill(1);
},
Here is the updated CodePen.

Related

vue3-Carousel scrolling issue with only two slides

I'm having an issue with wrap around scrolling when there are only two slides in the carousel. With the exact same setup, everything works correctly if there are three ore more slides, but with only two slides the carousel will only scroll Left to Right regardless of which navigation button I click or which direction I swipe. The order of the slides is correct, as is the pagination, it's just the animation that's incorrect. If I turn wrapAround scrolling off, I can correctly scroll the slides left or right, but with it turned on, they only scroll right. Here is the setup for the carousel and settings:
<carousel :settings="settings" ref="carouselRef">
<slide :key="index" v-for="(photo, index) of project.photos">
<div class="pic-outer">
<img
class="pic"
:src="photo"
draggable="false"
/>
</div>
</slide>
<template #addons>
<pagination
:style="{ opacity: project.photos.length == 1 ? 0.001 : 1 }"
/>
</template>
</carousel>
const settings = {
itemsToShow: 1,
itemsToScroll: 1,
wrapAround: true,
};
This issue is occurring even if I place the carousel in an empty component with no styling, so I can't think of anything else that could be interfering. I'm curious if anyone has run into this before or if there are any suggestions.
This was resolved by updating to the newest version of vue3-carousel.

How to refer to specific dynamically added component from number of dynamically added components in Vue, version 2.9

What or where is individual id or any other element that I can call to run a function on component.
Example: using add button I'm dynamically creating colored squares. Each square has close button.
Then I want to delete one of squares, let's say the blue one (third child of template).
v-bind:id='var' doesn't works because then all squares have the same id.
You can use ref, you can define ref in every added component. The ref is array. you can refrence component through index of the ref.
for example;<div v-for="(item) in arr" :key="item.id"> <span ref="testRef"> item.name </span> </div>, you can use 'this.$refs.testRef[index]' find component which you want.
There are multiple options. For instance, in your v-for loop you can get the index this way: (official docs)
<div v-for="(item, index) in myList" :key="index">
{{ item.name }}
</div>
You could then for example use the index in a ref to access the element for the script.
Another option is to pass the event instance to the onclick listener with the special keyword $event, and use this to get the element:
<div ... #click="myFunction($event)">
{{ item.name }}
</div>
And then in your script
myFunction(ev) {
// do something with the element that was clicked on
console.log(ev.target)
}
However, a more 'vue' way would be to not mess with the elements, but only manipulate the underlying data and let vue worry about representing the data with elements on your page. For instance, you could make your squares be represented by a list of objects, containing their own data own the state (opened or closed). So in your script you have:
data() {
return {
squares: [
{ color: "ff0000", opened: true },
...
]
}
},
And in your template something like
<div
v-for="square in squares"
v-show="suare.opened"
#click="square.opened = false"
> ...

Vue Components Losing Image When Rerendered

I have a sidebar component located in a view-router view component that renders several child component buttons. It renders the child components using v-for loops.
<div v-for="type in this.facebookLightButtons" :key="type">
<SidebarButton :type="type"/>
</div>
<div v-for="type in this.facebookButtons" :key="type">
<SidebarButton :type="type"/>
</div>
facebookLightButtons is simply an array of strings containing the text of the button (which is also the name of the image source of the button). The result is the following:
The corresponding code in the SidebarButton components are:
<template>
<div>
<router-link :to="'/' + capitalizeFirstLetter(type)" class="sidebar-button">
<table>
<tr>
<td>
<img class="sidebar-button-icon" :src="getImage" />
</td>
<td>
<p>{{capitalizeFirstLetter(type)}}</p>
</td>
</tr>
</table>
</router-link>
</div>
</template>
and
computed: {
getImage() {
return require('#/assets/images/SidebarIcons/' + this.type + '.png');
}
}
When I change to a new view-router view and then return to the home page where this sidebar is located, the images are all missing:
I am trying to figure out how to keep the images there when returning to the home page.
Things I have tried:
Clearing and setting the image source in the SidebarButton components in the created, beforeMount, mounted, activated, deactivated, updated, and unmounted lifecycle hooks (non of which seemed to work).
Clearing the image, waiting for 2000 milliseconds using setTimeout() and then setting the image to the correct image source
Wrapping both the contents of the SidebarButton template as well as the v-for loop in the parent component with a <keep-alive> tag
Hard coding each SidebarButton component instead of using a v-for loop
It seems like something must be missing. What can I do to ensure that these images stored locally on my computer not only show when first displayed, but also appear when the user returns to the homepage after entering a separate view-router view?

How to turn off drag slide in Vue agile

I am using vue-agile, and I have to show videos and images in it. The images work fine but for videos, whenever I drag the pointer to move to a certain position in the player, the slider drags and moves to the next slider. Is there any way to stop the drag/swipe feature. Thanks.
https://www.npmjs.com/package/vue-agile
As a workaround, I first watch the mouse events on the clicked element (#mousedown, #mouseup)
On mousedown, I set the swipe-distance prop to a very high pixel value in the example below I used 1,000,000,000 (Default is 50).
Doc: https://github.com/lukaszflorczak/vue-agile
This worked for my case.
<template>
<agile :dots="false" :infinite="false" :center-mode="true"
:nav-buttons="false" :swipe-distance="noSweep ? 1000000000 : 50" >
<div v-for="(card, index) in cards" :key="index">
<div
#mousedown="noSweep=true"
#mouseup="noSweep=false"
>
Card content - example
</div>
</agile>
</template>
<script>
export default {
data() {
return {
noSweep: false,
cards:['A','B','C']
}
}
}
</script>

Vue-strap Carousel: How to select specific slide

I have managed to create a carousel (slider) using Vue-strap carousel component with the following code:
<carousel>
<slider v-for="(photo,index) in photos" :key="photo.sequenceID" >
<img v-bind:src="'https://../photo/' + photo.photoFilename " >
</slider>
</carousel>
Carousel is working. I also display thumbnails of images on the page. I want to select a specific slide when I click a thumbnail.
How can I display a specific slide in the carousle? Is there a function in Vue-strap carousle or slider that can displays specific slide if I pass the slide number?
The following code will display the slide fo the pictureID. It uses the indicatorClick() method of the carousel component. Here vm is the Vue object name.
vm.$children[0].indicatorClick(pictureID);
Late reply:
You can use the navigateTo prop as follows:
template.vue > tamplate/transition
<carousel
:perPage="1"
:navigateTo="carouselPosition"
:navigationEnabled="true"
:paginationEnabled="false">
<slide>
...
</slide>
</carousel>
carouselPosition should be stored as a prop:
template.vue > export default {}
data () {
return {
carouselPosition: null // OR 1
}
}
Include the following on your thumbnail element:
template.vue > component thumbnail
v-on:click=";(carouselPosition = index)"
In this case the index value would be generated in a loop:
template.vue > component loop
v-for="(thumbnail, index) in yourData"
NOTE: Nuxtjs used in this example but it should easy to modify these examples to your needs.
Using v-model
See Carousel documentation;
Programmatically control which slide is showing via v-model (which binds to the value prop). Note, that slides are indexed starting at 0
<b-carousel
id="image-carousel"
controls
indicators
img-width="1024"
img-height="480"
v-model="currentSlide"
>
Inside my slide I use a img for every thumbnail. Upon click currentSlide is changed to the index of the thumbnail.
<img
v-on:click="showImage(index)"
/>
store currentSlide in data:
data() {
return {
currentSlide: 0
}
}
method for changing currentSlide
showImage (index) {
this.currentSlide = index;
}
Vue will update the value prop of the slider if the v-model reference is changed.
use v-bind:data-slide-to="index"
<ol class="carousel-indicators">
<li data-target="#carouselExampleIndicators"
v-for="(image, index) in images" v-bind:key="index"
v-bind:data-slide-to="index"
:class="{'active' : index===0}"></li>
</ol>