How to get current item index in v-carousel? - javascript

I have the following code that cycles a carousel which is fine but I want to be able to display the item title underneath as appose to on top of the image. I figured the way to do this is to create a new data value that is updated each time the carousel changes. I cannot figure out how to do this however.
<v-carousel>
<v-carousel-item
v-for="(item,i) in servicesCarouselItems"
:key="i"
:src="item.src"
>
</v-carousel-item>
</v-carousel>
<v-card-title class="justify-center">{{currentTitle}}</v-card-title>
<script>
export default {
data: () => ({
currentTitle: '',
servicesCarouselItems: [
{
name: "Title1",
src: require('../../1.jpeg'),
},
{
name: "Title2",
src: require('../../2.jpeg'),
},
{
name: "Title3",
src: require('../../3.jpeg'),
}
],
})
}
</script>

Propably best way is to use v-model - index of current item is exposed there...
<v-carousel v-model="currentIndex">
<v-carousel-item
v-for="(item,i) in servicesCarouselItems"
:key="i"
:src="item.src"
>
</v-carousel-item>
</v-carousel>
<v-card-title class="justify-center">{{ currentTitle }}</v-card-title>
<script>
export default {
data: () => ({
currentIndex: 0,
servicesCarouselItems: [
{
name: "Title1",
src: require('../../1.jpeg'),
},
{
name: "Title2",
src: require('../../2.jpeg'),
},
{
name: "Title3",
src: require('../../3.jpeg'),
}
],
}),
computed: {
currentTitle() {
return this.servicesCarouselItems[this.currentIndex].name
}
}
}
</script>

I managed to solve this issue by using the v-on:change / #change Vue event as shown in the example below.
<v-carousel #change="currentTitle = servicesCarouselItems[$event].name">
<v-carousel-item
v-for="(item,i) in servicesCarouselItems"
:key="i"
:src="item.src"
>
</v-carousel-item>
</v-carousel>
Further reading for those interested:
https://renatello.com/get-selected-value-on-change-in-vuejs/#The_advantages_of_using_change_event_instead_of_v-model_binding

Related

Vue: How to get rid of duplicate content

I have an array of names using v-for I get the names, as you can see I have two v-fors where the content is duplicated in this example my content is small and doesn't look so scary in real life it can be much bigger and all the problem is that the content is repeated, I tried to apply slots but could not cope
Template
<template>
<div>
<div v-for="(item, index) in array" :key="index" class="names">
<div class="show-names">
<p>{{ item.name }}</p>
</div>
<div
v-for="(girlNames, index) in item.girlNames"
:key="index"
class="names"
>
<div class="show-names">
<p>{{ girlNames.name }}</p>
</div>
</div>
</div>
</div>
</template>
Script
<script>
export default {
data() {
return {
array: [
{ name: "Alex" },
{ name: "Jacob" },
{ name: "Robert" },
{
girlNames: [
{
name: "Anna",
},
{
name: "Kiwi",
},
{
name: "Ava",
},
],
},
],
};
},
};
</script>
Yes, this picture shows where the content is repeated
You can also see code example in codesandbox
The only problem I see here is bad data structure. In my opinion it should be an object with two fields, which seperate in your case boys and girls, and in this object should be actual data:
<script>
export default {
data() {
return {
names: {
boys: [
{ name: "Alex" },
{ name: "Jacob" },
{ name: "Robert" },
],
girls: [
{ name: "Anna" },
{ name: "Kiwi" },
{ name: "Ava" },
]
}
},
],
};
},
};
</script>
They your code in template will be like:
<template>
<div>
<div class="names">
<div v-for="(item, index) in name.boys" :key="index" class="show-names">
<p>{{ item.name }}</p>
</div>
<div v-for="(item, index) in name.girls" :key="index" class="show-names">
<p>{{ item.name }}</p>
</div>
</div>
</div>
</template>

Why will vue draggable items not move between lists?

I am trying to create a card builder using Vue draggable. I have a row full of cardElements and these can be dragged to the card builder. The card builder is a rectangle made up of individual "buckets" of lists. Here is what it looks like:
Card builder Layout
Here is the script to generate the elements list:
import draggable from 'vuedraggable'
export default {
name: "clone",
display: "Clone",
order: 2,
components: {
draggable
},
data() {
return {
cardElements: [
{ name: "Logo", id: 1 },
{ name: "Stamp", id: 2 }
],
arrA: []
};
},
methods: {
log: function(evt) {
window.console.log(evt);
}
}
};
You can see that the cardElements are correctly rendered from script and this is how they are rendered in the HTML:
<draggable class="dragArea list-group" :list="cardElements" :group="{ name: 'people', pull: 'clone', put: false }" #change="log">
<div class="list-group-item" v-for="element in cardElements" :key="element.name">
{{ element.name }}
</div>
</draggable>
These are draggable and I can change their order like so:
Changed Order of items
Each "bucket" on the card is declared as an array like so (this is only for the top left space on the card builder, each square is a different number):
data() {
return {
cardElements: [
{ name: "Logo", id: 1 },
{ name: "Stamp", id: 2 }
],
arrA: []
};
}
<draggable class="dragArea list-group" :list="arrA" group="cardItem" #change="log">
<div class="lvl1-1 bucket empty" v-for="element in arrA" :key="element.name">
{{ element.name }}
</div>
</draggable>
But when I drag an element from the cardElements list to the arrA list, it doesn't move and I'm not sure why. I can get it working in the example code supplied here, but not when I change it to my own code.
The issue was that I had the group defined as :group="{ name: 'people', and then was calling it as group="cardItem" so I changed :group="{ name: 'people', to this :group="{ name: 'cardItem', and it worked

Vue.js: How do you change an icon and background color depending on the value of an item in a data table row?

I have a data table with politicains. A politician can have a party value of either Democrat or Republican. If a politician is a Democrat, I want to show an mdi-donkey icon next to "Democrat" and I want the color of the row to change to blue. For Republicans, show an mdi-elephant icon and change to red. I believe I'm supposed to use v-bind, I tried to, and wasn't having much luck. Here's my working code:
<template>
<v-card>
<v-card-title>
<v-text-field
v-model="search"
append-icon="mdi-magnify"
label="Search"
single-line
hide-details
></v-text-field>
</v-card-title>
<v-data-table
:headers="headers"
:items="politicians"
:search="search"
></v-data-table>
</v-card>
</template>
<script>
export default {
name: 'dashboard',
data(){
return{
search: '',
headers: [
{
align: 'start'
},
{text: 'Position', value: 'position'},
{text: 'Name', value: 'name'},
{text: 'Party', value: 'party'}
],
politicians: [
{
name: "John Smith",
party: "Democrat",
position: "County Executive"
},
{
name: "Bob Bush",
party: "Republican",
position: "County Executive"
},
{
name: "Elaina Krasinsky",
party: "Democrat",
position: "District Attorney"
},
{
name: "Robert Parson",
party: "Republican",
position: "District Attorney"
}
],
}
},
}
</script>
<style scoped>
.Democrat{
background-color: blue
}
.Republican {
background-color: red
}
</style>
I added styles for the background colors already. Can anyone get me on the right track?
Looks like you are using vuetify so this should be possible. You can use slots to customize certain colums. This could be like this in your case:
<v-data-table
:headers="headers"
:items="politicians"
:search="search"
>
<template v-slot:item.party="{item}" :class="functionWhichSetsClass(item.party)">
{{functionWhichShowsIcon(item.party)}}
</template>
</v-data-table>
In this example you only customize the column for party. So you can change the additional content and how it looks.

Vue draggable changes

I try to build simple tasks board and have one problem. I build my borad:
<draggable
v-for="(taskBoardCard, index) in filteredTasts"
:key="index"
:options="{ group: `${taskBoardCard}` }"
:class="{ 'roster__field--dark': isDarkModeOn }"
class="roster__field"
#change="log"
>
<task-card
v-for="task in taskBoardCard"
:key="task.id"
:task-item="task"
:class="`task--${task.status}`"
#open-current-modal="openEditingModal"
/>
</draggable>
But i cant see changes in my board:
methods: {
log (evt) {
window.console.log(evt)
}
}
In my filteredTasts i have
tasks: [
{
id: 1,
name: 'Task1',
description: 'description for task 1',
status: 'todo',
complexity: 6,
priority: 'low',
editing: false
}
]
How can i track actions in draggable?
Thank you.

Add an object to an array of objects vuetify model

I'm trying to save the value of a radio button dynamically loaded into an array of object. Thoose radios are options for a series of questions of a form, and i would like to get something like:
[{"question1":{
"selected": <id>,
...
},...]
But i don't know how should I define the data or how to reference it wiht the v-model attribute of the radio group.
This is my best try:
<v-radio-group v-model="answers[question.question_id]">
<v-row justify="center">
<v-col v-for="option in question.options" :key="option.option_id">
<v-radio
:label="option.option_text"
:name="question.question_id"
:value="option.option_id"
></v-radio>
</v-col>
</v-row>
</v-radio-group>
And data:
data: () => ({
...
answers: [],
...
}),
What I get rom this is somehting like: [anwswer_id1, anwswer_id1...], witch is close, but not exactly what I need
a simple way could be like this:
<template>
<v-layout column>
<v-radio-group v-model="questions[questionIndex][currentQuestionId].selected">
<v-row justify="center">
<v-col v-for="(option,i) in questions[questionIndex][currentQuestionId].options" :key="i">
<v-radio :label="option.text" :name="currentQuestionId" :value="option._id"></v-radio>
</v-col>
</v-row>
</v-radio-group>
<v-btn #click="handleClickButtonNext">next question</v-btn>
<v-btn #click="handleClickButtonPrev">previous question</v-btn>
</v-layout>
</template>
<script>
export default {
data() {
return {
questions: [
{
question0: {
selected: null,
options: [
{
text: "text 1",
_id: 1
},
{
text: "text 2",
_id: 2
},
{
text: "text 3",
_id: 3
}
]
}
},
{
question1: {
selected: null,
options: [
{
text: "text 2",
_id: 2
},
{
text: "text 3",
_id: 3
},
{
text: "text 4",
_id: 4
}
]
}
},
],
questionIndex: 0
};
},
computed: {
currentQuestionId() {
return "question" + this.questionIndex;
}
},
methods: {
handleClickButtonNext() {
if (this.questionIndex < this.questions.length-1) this.questionIndex++;
},
handleClickButtonPrev() {
if (this.questionIndex > 0) this.questionIndex--;
},
}
};
</script>
where:
questionIndex - keeps track of the current question index
currentQuestionId - gives you the current question id
handleClickButtonNext / handleClickButtonPrev - lets you jump between the questions
This is a way if you just want to show 1 question at a time.
Otherwise, you could also get rid of keeping track of the index, and loop the questions array:
<template>
<v-layout column>
<v-radio-group
v-for="(question, j) in questions"
:key="j"
v-model="question[`question${j}`].selected"
>
<v-row justify="center">
<v-col v-for="(option,i) in question[`question${j}`].options" :key="i">
<v-radio :label="option.text" :name="`question${j}`" :value="option._id"></v-radio>
</v-col>
</v-row>
</v-radio-group>
</v-layout>
</template>
<script>
export default {
data() {
return {
questions: [
{
question0: {
selected: null,
options: [
{
text: "text 1",
_id: 1
},
{
text: "text 2",
_id: 2
},
{
text: "text 3",
_id: 3
}
]
}
},
{
question1: {
selected: null,
options: [
{
text: "text 2",
_id: 2
},
{
text: "text 3",
_id: 3
},
{
text: "text 4",
_id: 4
}
]
}
}
]
};
}
};
</script>

Categories