I am building a new/edit item form using Vuetify(v2.6.3). My form has multiple combobox's that pull their items from a backend API as objects. I would like to be able to add new items, which the combobox is able to do. However, when I add a new item it's added as a string. Is there a way to add that new item as an object instead?
I only need the new object to have a name key in order to send it to the API to be created
Desired New item from v-combobox:
{
name: 'New Item',
}
Simplified list of items returned from API and available as combobox choices:
[
{
id: 1,
name: 'Item 1',
createdAt: '2020-01-01',
updatedAt: '2020-01-01'
},
{
id: 2,
name: 'Item 2',
createdAt: '2020-01-01',
updatedAt: '2020-01-01'
},
{
id: 3,
name: 'Item 3',
createdAt: '2020-01-01',
updatedAt: '2020-01-01'
}
]
Here is a simplified version of my Form:
<template>
<v-card>
<v-card-title>
<span >Edit Item</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col>
<v-combobox
v-model="item"
:items="items"
item-text="name"
item-value="id"
label="ComboBox"
return-object
></v-combobox>
</v-col>
</v-row>
</v-container>
</v-card-text>
</v-card>
</template>
<script>
export default {
name: 'TestForm',
data() {
return {
item: null,
items: [
{
id: 1,
name: 'Item 1',
createdAt: '2020-01-01',
updatedAt: '2020-01-01',
},
{
id: 2,
name: 'Item 2',
createdAt: '2020-01-01',
updatedAt: '2020-01-01',
},
{
id: 3,
name: 'Item 3',
createdAt: '2020-01-01',
updatedAt: '2020-01-01',
},
],
}
},
}
</script>
In my method which sends the form to the API, I could check the value of each combobox and convert to an object if needed, but I am wondering if it's possible to handle it in the combobox component.
CodePudding user response:
VComboBox doesn't seem to support that, but you could workaround it by using the component's change-event to add a new object with the entry if needed:
Add a
change-event handler (e.g., namedonChange) on thev-combobox.In
onChange(), lookup the entry initemsbyname(i.e., corresponding to theVComboBox'sitem-textprop).If found, set
itemto the existing item.Otherwise, create a new object with that entry, and set
itemto the newly created object. Note the new object'sid(i.e., corresponding toVComboBox'sitem-valueprop) must be unique forVComboBoxto create and track it.
<v-combobox
v-model="item"
@change="onChange" 1️⃣
/>
let nextId = 1
export default {
⋮
methods: {
addItem(name) {
const newItem = {
id: nextId ,
name,
}
this.items.push(newItem)
return newItem
},
1️⃣
onChange(entry) {
if (typeof entry === 'string' && entry.trim()) {
2️⃣
const item = this.items.find(item => item.name === entry)
if (item) {
3️⃣
this.item = item
} else {
4️⃣
this.item = this.addItem(entry)
}
}
},
},
}
CodePudding user response:
It does not appear that a ComboBox can directly return an object when adding a new item. However it looks like you can leverage the input event of the component to run a method that converts to an object.
Here is how I call the method on the component's input event:
<v-combobox
v-model="item"
:items="items"
item-text="name"
item-value="id"
label="ComboBox"
return-object
@input="makeObject"
></v-combobox>
@input="makeObject" listens for the component's input event and calls the makeObject method and passes the currently selected item
Then I was able to write a method which checks if the combobox value is a string. If so then it converts it to an object
<script>
export default {
name: "TestForm",
data() {
return {
item: null
// Remaining code omitted for readability
}
}
methods: {
makeObject(val) {
if (typeof val === "string") {
this.item = {
name: val,
};
}
},
},
};
</script>
Here is my full component:
<template>
<v-card>
<v-card-title>
<span >Edit Item</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col>
<v-combobox
v-model="item"
:items="items"
item-text="name"
item-value="id"
label="ComboBox"
return-object
@input="makeObject"
></v-combobox>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-text>
{{ item }}
</v-card-text>
</v-card>
</template>
<script>
export default {
name: "TestForm",
data() {
return {
item: null,
items: [
{
id: 1,
name: "Item 1",
createdAt: "2020-01-01",
updatedAt: "2020-01-01",
},
{
id: 2,
name: "Item 2",
createdAt: "2020-01-01",
updatedAt: "2020-01-01",
},
{
id: 3,
name: "Item 3",
createdAt: "2020-01-01",
updatedAt: "2020-01-01",
},
],
};
},
methods: {
makeObject(val) {
if (typeof val === "string") {
this.item = {
name: val,
};
}
},
},
};
</script>
