Allow Multiple Chips with the same value in a v-combobox - vue.js

how can I add new chips with the same value in the Combobox that I am using? For example every time I add 200 and I want to add another 200 it is automatically deleted.
I want to save the user inputs in an array like [100, 200, 200, 300]
<v-combobox
v-if="points.number_compartments > 1"
v-model="compartments_detail"
chips
label="CAPACIDAD DE COMPARTIMIENTOS"
clearable
deletable-chips
append-icon=""
multiple
outlined
dense
class="mx-3"
>
<template v-slot:selection="{ attrs, item, selected, index }">
<v-chip
small
v-bind="attrs"
:input-value="selected"
close
#click:close="removeChips(index)"
color="primary"
>
<span>{{index + 1}} </span> - {{ item }} <span class="mx-1"> (gls) </span>
</v-chip>
</template>
</v-combobox>

If you would like to use duplicated items, it's better to use an array of objects data structure and give every duplicate item a unique value so the items can be identified by the item-value prop and allow selecting duplicates.
The component code would be like this-
<v-combobox
v-if="points.number_compartments > 1"
:items="items"
item-text="label"
item-value="id"
v-model="compartments_detail"
chips
label="CAPACIDAD DE COMPARTIMIENTOS"
clearable
deletable-chips
append-icon=""
multiple
outlined
dense
class="mx-3"
>
<-- YOUR CODE ->
</v-combobox>
And the structure of the items would be-
items: [
{
label: 100,
id: 1
},
{
label: 100,
id: 2
},
{
label: 200,
id: 3
},
{
label: 200,
id: 4
}
]

Related

How to show multiple attributes while selecting items in v-autocomplete?

How do I achieve v-autocomplete to show both the value and text when selecting?
Here is my code-
<v-autocomplete
v-model="request"
v-if="products.data"
:items="products.data"
outline
chips
label="Select item"
item-text="name"
item-value="id"
>
products: [
{
text: "Apple",
value: 209
},
{
text: "Banana",
value: 229
}
]
Currently, I am able to display only the text but I want two display both (text and value in the options) before selecting.
Using slots you can do this-
<v-autocomplete
:items="products"
label="Select"
item-text="text"
item-value="value"
>
<!-- If you want to modify the selected data -->
<template v-slot:selection="data">
{{ data.item.text }} {{ data.item.value }}
</template>
<!-- If you want to modify the list options -->
<template v-slot:item="data">
{{ data.item.text }} {{ data.item.value }}
</template>
</v-autocomplete>

Select All functionality to select filtered items in vuetify combobox

I'm using vuetify combobox and the select all is working as expected as described in How to have a "select all" option on a v-select or v-combobox?.
What I'm trying to achieve is - when I check the Select All, it should select all the filtered values from the list.
In this example, I've typed "Pha..." and what I'm trying to achieve is to get the filtered list to be returned.
The Combobox is as below -
<v-combobox v-if="editedIndex == -1"
label='Phase'
v-model='editedItems.selected_values'
:items='phases'
item-value='pp_code'
item-text='phasedetails'
class="pl-2 pr-2"
multiple
chips
>
<template v-slot:prepend-item>
<v-list-item
ripple
#click="toggle(); editedItems.selected_values.length = phases.length;"
>
<v-list-item-action>
<v-icon :color="editedItems.selected_values.length > 0 ? 'indigo darken-4' : ''">
{{ icon }}
</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
Select All
</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-divider class="mt-2"></v-divider>
</template>
</v-combobox>
The toggle function is as below -
toggle () {
this.$nextTick(() => {
if (this.likesAllFruit) {
console.log("Select all clicked")
this.selectedFruits = []
console.log("Typed value is ")
console.log(this.editedItems.phase_code)
console.log("Selected values ")
console.log(this.editedItems.selected_values)
this.alreadySelectedPhases.push(this.editedItems.selected_values)
console.log(this.alreadySelectedPhases)
console.log(this.phases.length)
} else {
this.editedItems.selected_values = this.phases.slice()
}
})
},
I'm not getting the typed value until the combobox is selected so that we can filter the list by the typed value and return.
Please let me know if anyone has any idea on how we can achieve it. Or if we have any inbuilt method for it.
Thanks in Advance.

Display value derived from field instead of field itself in q-table column

I have a role for a specific user with these numbers.
Instead of number 1 it will display the word "Super Admin"
Instead of number 2 it will display the word "Admin"
Instead of number 2 it will display the word "User"
and so on.
I am using q-table
<q-table
flat
bordered
title="USERS"
:data="allUsers"
:columns="columns"
:filter="filter"
:pagination.sync="initialPagination"
row-key="id"
>
<template v-slot:top-right>
<q-input
outlined
dense
debounce="300"
placeholder="Search"
v-model="filter"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<div class="q-pa-sm q-gutter-sm"></div>
<q-btn
outline
color="white"
text-color="black"
#click="openCreateUserModal"
label="Create Users"
/>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols.filter(col => col.name !== 'actions')"
:key="col.name"
>
{{ col.value }}
</q-td>
<td key="actions">
<q-btn dense flat color="primary" field="edit" icon="edit" />
<q-btn
dense
flat
color="negative"
field="delete"
icon="delete"
/>
</td>
</q-tr>
</template>
</q-table>
The role in my column
{
name: "role",
align: "center",
label: "Role",
field: "role",
sortable: true
},
Is this possible what I'm trying to achieve?
Column definition can contain format field to define a custom formatting function. The function is called with the 2 arguments - the value retrieved from field and row (which can be useful to create display values by combining data from multiple fields)
const roleIdToRoleName = {
1: "Super Admin",
2: "Admin",
3: "User"
}
...
{
name: "role",
align: "center",
label: "Role",
field: "role",
sortable: true,
format: (val, row) => roleIdToRoleName[val]
},
This works out of the box if you do not override default rendering by providing body slot. This is problematic because you will loose a lot of provided functionality:
field can be string but it can also be a function (useful to drill down to some nested object data)
format is of course not applied
Default "get cell value" functionality of q-table looks like something like this:
const getCellValue(row, col) {
const val = typeof col.field === 'function' ? col.field(row) : row[col.field]
return col.format ? col.format(val, row) : val
}
You can of course replicate it in your code and use it:
<q-td :props="props" // !! you are missing props here
v-for="col in props.cols.filter(col => col.name !== 'actions')"
:key="col.name"
>
{{ getCellValue(props.row, col) }}
</q-td>
but since it seems only reason you are overriding body slot is because you need custom rendering of the actions column, why not just use body-cell-actions slot instead? This will override only rendering of actions column and other columns will use default q-table rendering
Just add actions column in columns definition:
{ name: 'actions', label: 'Action', sortable: false}
<template v-slot:body-cell-actions="props">
<q-td :props="props">
<q-btn dense flat color="primary" field="edit" icon="edit" />
<q-btn dense flat color="negative" field="delete" icon="delete" />
</q-td>
</template>

Change style and colors of chips in v-select

How can I change the color and style of chips in v-select?
I have code like this:
<v-select
v-model="value"
:items="roles"
:menu-props="{ top: true, offsetY: true }"
small-chips
label="Roles"
multiple
hint="Select the role"
persistent-hint
>
</v-select>
How can I change chips to styled label and color blue?
You probably want the selection slot.
<v-select
v-model="value"
:items="roles"
:menu-props="{ top: true, offsetY: true }"
small-chips
label="Roles"
multiple
hint="Select the role"
persistent-hint>
<template #selection="{ item }">
<v-chip color="blue">{{item.name}}</v-chip>
</template>
</v-select>
Where item.name would depend on these individual items of roles.
If we use selection slot to customize the chip as we want like #YomS. show above, we cannot use chips and deletable-chips props to make that chip deletable.
For anyone also need to implement deletable-chips in selection slot, here my snippet:
<template>
<v-select
v-model="styleSelection" // Linking that v-select to one array
clearable
multiple
:items="travelStyles"
label="Travel Style"
>
<template #selection="{ item }">
<v-chip
color="primary"
close
#click:close="deleteChip(item, styleSelection)" // call a method deleteChip
>{{ item }}</v-chip
>
</template>
</v-select>
</template>
<script>
export default {
data: () => ({
styleSelection: [],
travelStyles: [
'Discovery',
'Family',
'In-depth Cultural',
'Historical',
'Food & Culinary',
'Adventure',
'Beach',
'Hiking & Trekking',
'Bicycle',
'Sightseeing',
'Boat',
'River Cruise',
'Ocean Cruise',
],
}),
methods: {
deleteChip(itemNeedToRemove, array) {
for (let i = 0; i < array.length; i += 1) {
if (array[parseInt(i, 10)] === itemNeedToRemove) {
array.splice(i, 1);
}
}
},
},
};
</script>
Beside Selects v-select, it also works with Autocomplete v-autocompletes, the snippet is exactly the same.
If you want to customize the chip color and make it deletable in V-autocompletes, you can take the look on the code below:
<v-autocomplete
v-model="citySelection"
clearable
multiple
:items="city"
label="Where do you want to go?"
:search-input.sync="search"
#change="search = ''"
>
<template #selection="{ item }">
<v-chip
close
color="primary"
#click:close="deleteChip(item, citySelection)"
>{{ item }}</v-chip
>
</template>
</v-autocomplete>
I have been in your shoes and I think that, if you need deleteable chips, reimplementing the delete chip functionality just for the sake of changing a color is an overkill.
Since your goal is stylistic I would suggest that you use a simple scss solution:
<template>
<v-select
class="mySelect"
v-model="value"
:items="roles"
:menu-props="{ top: true, offsetY: true }"
small-chips
label="Roles"
multiple
hint="Select the role"
persistent-hint
deletable-chips
>
</v-select>
</template>
<script>
export default {
data() {
return {
roles: ['role1', 'role2'],
}
},
}
</script>
<style lang="scss" scoped>
.mySelect::v-deep .v-chip {
/* chip background color */
background-color: var(--v-primary-base);
/* chip text color */
color: white;
/* chip X color */
button {
color: white;
}
}
</style>
Notice the .mySelect::v-deep selector that enables the rule to apply in the specific element, even in a scoped style block.
EDIT:
Included Andy's suggestion
Added explanatory comments in style
Removed unnecessary !important
Added dummy roles in data to make the answer
copy/paste testable

using v-model in a v-for directive to create a new data object

I'd like to create an items object with a v-for directive in the following way:
<v-row v-for="(item, index) in items" v-bind:key="index">
<v-col cols="12" md="4">
<v-autocomplete
v-model="item.product_uid"
:items="product_list"
item-text="[attributes][name]"
item-value="id"
label="Product name"
outlined
></v-autocomplete>
</v-col>
<v-col cols="12" md="4">
<v-text-field
v-model="item.qty"
label="Quantity"
outlined
></v-text-field>
</v-col>
<v-col cols="12" md="4">
<v-text-field
v-model="item.net_unit_price"
label="Unit price"
outlined
></v-text-field>
</v-col>
</v-row>
<v-col>
<v-btn rounded color="primary" dark #click="addItem()">Add</v-btn>
</v-col>
data () {
return {
items: [],
product_list: [],
}
},
methods: {
addItem: function () {
this.items.push({ product_uid: '', qty: '', net_unit_price: '', });
}
}
How can I get the "Unit price" value (product_list[attributes][price]) based on the selected "Product name" from the product_list object and than add it to the new items array?
The product_list object come from a http call from the server and I'd like to use these datas as a default value in the form and - if necessary - change the values and add them all to the new item object.
Thanks a lot for your help!
Most probably, you should use computed property as noticed at documentation https://v2.vuejs.org/v2/guide/computed.html .
Also your product_list is empty. Before getting product_list[attributes][price] you should add something to it or get filtered result with help of computed properties or something else. Also, I don't understand what you are trying to do with that line of code :items="product_list" You are trying to set the same value to the items property of all components.
It's hard to understand what exactly you want to do, but probably, also you will need some kind of filter methods https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter .
If I understand you correctly, you want to "autocomplete" the quantity and unit price when choosing an item from the autocomplete list. So here's a sample. Let's say your api data looks like:
product_list: [
{product_uid: 1, name: 'name1', qty: 1, net_unit_price: 2},
{product_uid: 2, name: 'name2', qty: 2, net_unit_price: 3},
{product_uid: 3, name: 'name3', qty: 3, net_unit_price: 4}
],
Then remove the v-model and item-value from your autocomplete, and instead add return-object, so that we get the complete object from the autocomplete to use. Add the vuetify autocomplete event change, so that we can pass the object chosen and the index so that we can patch the value to your array:
Template:
<v-autocomplete
:items="product_list"
item-text="name" <!-- add correct prop -->
label="Product name"
outlined
return-object <!-- add this and below -->
#change="setValue(index, $event)"
></v-autocomplete>
So now when an item is chosen from the autocomplete, we call setValue, and we patch the correct values for it:
setValue: function(index, item) {
// if you want the complete object, else choose which props you want
this.$set(this.items, index, { ... item })
}
CODEPEN