How to add same item multiple times with Vuetify v-select - vue.js

Vuetify provides a select field component that is used for collecting user provided information from a list of options.
Here for the documentation
The component works with check boxes, so each time you check an item, it is added at the end of the list.
Now what I'd like to do is adding the same item on the list multiple times, so each time you click the item it is added at the end of the list. Is this achievable with Vuetify?

So the image is a bit misleading. If you would like to get tag input with autosuggestions, then I would rather keep it separate.
It would be possible to enhance the example below with v-text-field, but feels kinda hacky to me.
Please let me know how does this solution suite you :)
new Vue({
el: '#app',
vuetify: new Vuetify({ icons: { iconfont: 'md' } }),
data: () => ({
options: [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 3, name: 'fizz' }],
value: [
{ id: 1, name: 'foo' },
{ id: 1, name: 'foo' }
],
}),
})
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app id="inspire">
<v-container fluid>
<v-row>
<v-col cols="12" sm="12">
<v-chip class='mr-2' v-for='({id, name}, i) in value'>
{{ id }}: {{ name }}
<v-icon class='ml-2' small #click='value.splice(i, 1)'>close</v-icon>
</v-chip>
<v-menu>
<template v-slot:activator='{ on }'>
<v-btn icon v-on='on' class='green'>
<v-icon>add</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item v-for='o in options' #click='value.push(o)'>
<v-list-item-title>{{ o.name }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-col>
<v-col>
<pre>{{ value }}</pre>
</v-col>
</v-row>
</v-container>
</v-app>
</div>

If you have items with same name, you need to use it's distinct property (here it is "id") to tell the difference.
and use item-text & item-value as shown in the example.
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 3, name: 'foo' },
{ id: 4, name: 'fizz' },
{ id: 5, name: 'bar' }],
value: null,
}),
})
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app id="inspire">
<v-container fluid>
<v-row align="center">
<v-col cols="12" sm="6">
<v-select v-model="value" :items="items" item-text="name" item-value="id" attach chips label="Chips" multiple></v-select>
</v-col>
<v-col>
<pre>{{ value }}</pre>
</v-col>
</v-row>
</v-container>
</v-app>
</div>

Related

How to not loop a particular item in a card in vuetify

can Any one help me... I want to show card-title only in card-1. I don't want to show the card-title in card-2 card-3 and card-4.
<v-app>
<v-row v-for="(item, index) in list" :key="index">
<v-col cols="12">
<v-card>
<v-card-title>
<v-avatar size="60" color='primary'>{{item.avatarText}}</v-avatar>
</v-card-title>
<v-card-text>{{item.name}}</v-card-text>
</v-card>
</v-col>
</v-row>
</v-app>
</template>
<script>
export default{
data(){
return{
list:[{name:'apple1',avatarText:'Abc',},
{name:'apple2'},
{name:'apple3'},
{name:'apple4'}]
}
}
Using v-if, you can check for the index:
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: () => ({
list:[ {name:'apple1', avatarText:'Abc'}, {name:'apple2'}, {name:'apple3'}, {name:'apple4'} ]
})
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script><link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<v-app id="app">
<v-row v-for="(item, index) in list" :key="index">
<v-col cols="12">
<v-card>
<v-card-title v-if="index === 0">
<v-avatar size="60" color='primary'>{{item.avatarText}}</v-avatar>
</v-card-title>
<v-card-text>{{item.name}}</v-card-text>
</v-card>
</v-col>
</v-row>
</v-app>

vuetify :v-date-picker error on changing calendar type

to see error
1.switch type to month
2.select a months range
3.change type to date
then you will see this error :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
modal : false ,
currentLocale : 'en',
selectOptions : [
{ key: 'date', value: 'Date' },
{ key: 'month', value: 'Month' }
],
calType : 'date',
range : true,
date : []
}
},
methods: {
selectType($event) {
this.calType = $event;
},
},
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app id="inspire">
<v-row justify="center">
<v-col cols="12">
<v-select
v-model="calType"
label="select date type"
item-text="value"
item-value="key"
:items="selectOptions"
dense
single-line
v-on:change="selectType($event)"
>
</v-select>
</v-col>
<v-col cols="12">
<v-dialog
ref="dialog"
v-model="modal"
:return-value.sync="date"
persistent
width="290px"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-model="date"
label="Picker in dialog"
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="date"
:locale="currentLocale"
:range="range"
:type="calType"
:first-day-of-week="1"
scrollable
>
<v-spacer></v-spacer>
<v-btn text color="primary" #click="modal = false">
Cancel
</v-btn>
<v-btn text color="primary" #click="$refs.dialog.save(date)">
OK
</v-btn>
</v-date-picker>
</v-dialog>
</v-col>
</v-row>
</v-app>
</div>
so, how can i fix this ?
also this is another photo

Vuetify: v-date-picker error , when a month is selected , then type changed to date

I am using v-date-picker component
when I select a month and then
change type props from month to date
using a select option that I provided in the from .
I see an error
and this is vuetify date-picker component
<v-date-picker
full-width
:locale="currentLocale"
v-model="form.date"
:range="range"
:type="calType"
:first-day-of-week="1"
>
</v-date-picker>
so, how can I fix this error ?
I don't know why you are getting this error but this is how you can change the type of date picker
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
currentLocale: 'en',
selectOptions: [{key: 'date', value: 'Date'}, { key: 'month', value: 'Month'}],
calType: 'date',
range: '',
picker: '',
}
},
methods: {
selectType($event) {
this.calType = $event;
},
},
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<div id="app">
<v-app id="inspire">
<v-row justify="center">
<v-col>
<v-select
v-model="calType"
label="select date type"
item-text="value"
item-value="key"
:items="selectOptions"
dense
single-line
:first-day-of-week="1"
:range="range"
v-on:change="selectType($event)"
>
</v-select>
</v-col>
<v-col>
<v-date-picker v-model="picker" :type="calType"></v-date-picker>
</v-col>
</v-row>
</v-app>
</div>
</div>
I don't know why you are getting this error but this is how you can change the type of date picker
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
currentLocale: 'en',
selectOptions: [{key: 'date', value: 'Date'}, { key: 'month', value: 'Month'}],
calType: 'date',
range: '',
}
},
methods: {
selectType($event) {
this.calType = $event;
},
},
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<div id="app">
<v-app id="inspire">
<v-row justify="center">
<v-col>
<v-select
v-model="calType"
label="select date type"
item-text="value"
item-value="key"
:items="selectOptions"
dense
single-line
v-on:change="selectType($event)"
>
</v-select>
</v-col>
<v-col>
<v-date-picker v-model="picker" :type="calType"></v-date-picker>
</v-col>
</v-row>
</v-app>
</div>
</div>

Why does Vue render component incorrectly?

Below is an example of an error.
Reproduce the problem: Add 3 items and remove the second.
Everything inside is deleted correctly. This can be seen from the rendering of the text below. But the component is not displayed correctly. Why? Is this a bug?
I tried to use an additional property for conditional rendering, tried to overwrite references to an array of elements and inside the array - no results.
Vue.component('selected-material', {
props: [
'value'
],
template: `
<div>
<v-autocomplete
v-model="local"
:items="materials"
item-text="name"
return-object
autocomplete="new-password"
#change="input"
/>
</div>
`,
data() {
return {
local: this.value,
materials: [{
id: 1,
name: 'mat-1',
q: 1
},
{
id: 2,
name: 'mat-2',
q: 1
},
],
};
},
methods: {
input() {
this.$emit('input', this.local);
},
},
})
Vue.component('add-board', {
props: [
'value'
],
template: `
<div>
<v-container fluid class="my-0 py-0">
<v-row class="my-0 py-0">
<v-col class="my-0 py-0">
<selected-material
v-model="local.material"
/>
</v-col>
<v-col class="my-0 py-0">
<v-text-field
class="my-0 py-0"
v-model="local.material.q"
/>
</v-col>
<v-col class="my-0 py-0">
<v-row class="my-0 py-0">
<v-col class="my-0 py-0">
<v-btn
class="my-0 py-0"
color="success"
icon
#click="append"
>
<v-icon>mdi-plus</v-icon>
</v-btn>
</v-col>
<v-col class="my-0 py-0">
<v-btn
class="my-0 py-0"
color="error"
icon
#click="remove"
>
<v-icon>mdi-minus</v-icon>
</v-btn>
</v-col>
</v-row>
</v-col>
</v-row>
</v-container>
</div>
`,
data() {
return {
local: this.value,
};
},
methods: {
input() {
this.$emit('input', this.local);
},
append() {
this.$emit('append');
},
remove() {
this.$emit('remove', this.local.id);
},
},
})
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
boards: [],
};
},
mounted() {
this.append();
},
methods: {
append() {
this.boards.push({
id: Date.now(),
material: {
id: 1,
name: 'mat-1',
q: 1
},
});
},
remove(id) {
if (this.boards.length !== 1) {
const index = this.boards.findIndex(board => board.id === id);
this.boards.splice(index, 1);
}
},
},
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-main>
<v-row v-for="(board, index) in boards" :key="index">
<v-col>
<add-board :key="index" v-model="boards[index]" #append="append" #remove="remove" />
</v-col>
</v-row>
<v-row v-for="(board, index) in boards" :key="`_${index}`">
<v-col>
{{ board.id }} | {{ board.material.q }}
</v-col>
</v-row>
</v-main>
</v-app>
</div>
UPD:
After replaced with ID:
When removing items from a v-for list, it's important to use a key that's unique to each item if you don't want the DOM to be reused. If you use index and remove an item, the next item takes its index, so Vue reuses the DOM of the removed item.
Use the id as a key, since that seems to be unique:
<v-row v-for="(board, index) in boards" :key="board.id">
Also, check the v-model on the <v-text-field>, it seems like you might intend for it to use local.material.q rather than local.q:
<v-text-field
class="my-0 py-0"
v-model="local.material.q"
/>

When I delete one in the v-expansion-panel it opens the next one for me. How to undo it

expansion-panel and when I delete one from the array it automatically opens the next one for me.
how can I undo it?
Thanks
<v-expansion-panel
v-for="(Test, index) in Test"
:key="index">
<v-expansion-panel-header>
<template v-slot:actions>
<v-icon color="green">fa fa-check</v-icon>
</template>
</v-expansion-panel-header>
<v-expansion-panel-content>
<v-col cols="4">
<v-btn
text
color="primary"
#click="
delete(Test)
"
>delete</v-btn
>
</v-col>
</v-expansion-panel-content>
</v-expansion-panel>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
active: null,
test: [1, 2, 3, 4, 5]
}),
methods: {
del(index) {
this.test.splice(index, 1)
this.active = null
}
}
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-main>
<v-container>
<v-expansion-panels v-model="active">
<v-expansion-panel v-for="(t, index) in test" :key="index">
<v-expansion-panel-header>
item
</v-expansion-panel-header>
<v-expansion-panel-content>
<v-col cols="4">
<v-btn text color="red" #click="del(index)">delete{{t}}</v-btn>
</v-col>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</v-container>
</v-main>
</v-app>
</div>
Using value prop:
Controls the opened/closed state of content in the expansion-panel. Corresponds to a zero-based index of the currently opened content.
Set this.active = null after each deletion to keep the panel closed.