I have the following v-select in my code:
<v-select
v-if='d.length'
v-model='ci'
:items='d'
item-text='value.name'
item-value='value.name'
label='label'
multiple='multiple'
height='60'
small-chips
single-line
solo
@change='itemChanged'
>
<template v-slot:prepend-item v-if='multiple && title && d.length'>
<v-list-tile
ripple
@click="action"
>
<v-list-tile-action>
<v-icon :color="ci.length > 0 ? 'indigo darken-4' : ''">{{ icon }}</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{title}}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-divider class="mt-2"></v-divider>
</template>
<template v-slot:selection="{ item, index }">
<v-chip v-if="index === 0">
<span>{{ item.text }}</span>
</v-chip>
<span
v-if="index === 1"
class="grey--text caption"
>(+{{ checkedItems.length - 1 }} others)</span>
</template>
</v-select>
It receives its model, items and other defs as props. Model and Items are identical arrays of objects with the following structure:
{text: 'text', value: {name: 'foo'}}
So essentially all the items are selected when the component is mounted.
Once the user clicks on an item from the list, I want to receive in my itemChanged
method either the entire object, or at least the value object. For time being I only want to console log the received object:
itemChanged(value) {
console.log('Changed item', value);
}
But it prints the entire model array, minus the clicked item
Tried to use return-object
, tried to change the item-value and change the objects structure - always the same result.
Any ideas how can I get only the clicked item object/value?
Does something like this work, or am I misunderstanding your question? This outputs selected items (as objects) back on the page versus console.log(...)
.
Edit: (answering your question below) ~~Slot Props~~: (not to be confused with 'named slots') essentially allow you to take properties from the child component and use them to render in the parent. You can read more on scoped slots (also known as 'slot props') here
Take the follow code block for example:
<template v-slot:item='data'>
<v-list-tile-content>
<v-list-tile-title>
{{ data.item.firstName }} {{ data.item.lastName }}
</v-list-tile-title>
</v-list-tile-content>
</template>
v-slot:item='data'
- you could use any name you wanted in place of data: v-slot:item="theItems"
would also work (note: you would then use {{ theItems.item.firstName }}...
The reason you have to use data.ITEM.x
(referring to ITEM
) is because that is what Vuetify calls that scoped slot
for v-select
- you can read more on that here .. Hope this helps!
new Vue({
el: "#app",
props: {
value: {
type: [String, Object]
}
},
data() {
return {
chosenItems: [],
items: [{
firstName: "John",
lastName: "Smith",
Age: 44
},
{
firstName: "Sarah",
lastName: "Martin",
Age: 32
},
{
firstName: "Derick",
lastName: "Johnson",
Age: 39
},
{
firstName: "Mary",
lastName: "Spitzer",
Age: 22
},
{
firstName: "Wendy",
lastName: "Macdonald",
Age: 57
},
]
};
},
computed: {
selectedItems: {
get() {
return this.value;
},
set(item) {
// Could either emit (so you can use v-model on the parent)
// or add to array
this.chosenItems.push(item)
this.$emit("input", item);
}
}
}
});
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<div id="app">
<v-app>
<v-content>
<v-container>
<v-layout row>
<v-flex>
<v-select
v-model='selectedItems'
label='Select One Or Many'
:items="items"
item-text="firstName"
chips
clearable
multiple
return-object
>
<template v-slot:selection='data'>
<v-chip
:key="JSON.stringify(data.item)"
close
class="chip--select-multi"
@input="data.parent.selectItem(data.item)"
>
{{ data.item.firstName }} {{ data.item.lastName }}
</v-chip>
</template>
<template v-slot:item='data'>
<v-list-tile-content>
<v-list-tile-title>
{{ data.item.firstName }} {{ data.item.lastName }}
</v-list-tile-title>
</v-list-tile-content>
</template>
</v-select>
</v-flex>
</v-layout>
<div class="mt-5">
<v-layout>
<v-flex>
<h3>Chosen Items Will Be Displayed Here:</h3>
</v-flex>
</v-layout>
<div v-for="(chosen, index) in chosenItems">
<hr/>
<div v-for="(eachChosen, i) in chosen">
{{ eachChosen }}
</div>
<hr/><br/>
</div>
</div>
</v-container>
</v-content>
</v-app>
</div>