Vue-select tipps with Inertia & Laravel

Dr. Adam Nielsen
2 min readNov 23, 2023

How to use vue-select with Vue 3 and Laravel. https://vue-select.org/

Basics

The most simplest way to introduce a v-select component is by specifying its options and the model.

<v-select :options="options" v-model="form.address"></v-select>

ID different from value

The variable `options` needs to be an array, if your id is different from your options label. Each option has an id and a label:

public function create()
{
$options = [
['id' => 'de', 'label' => 'Germany'],
['id' => 'uk' , 'label' => 'United Kingdom']
];
return Inertia::render('Welcome', compact('options'));
}

This comes with a new issue, the value of form.address is not a simple value anymore, but an object containing both an ID and a label. This complicates form submission, as you need to extract the ID from the object. Additionally, it poses challenges in editing scenarios where pre-selecting values requires more than just an ID—you need to provide the whole id/label object. To resolve this, you should use the :reduce attribute in your v-select component. By doing so, as shown in the code snippet:

<v-select :options="options" v-model="form.address" :reduce="(option) => option.id"></v-select>

This modification ensures that form.address will store only the ID, simplifying both the handling of pre-defined values and the process of submitting form data.

    public function edit()
{
$options = [
['id' => 'de', 'label' => 'Germany'],
['id' => 'uk' , 'label' => 'United Kingdom']
];
// It is enough to just provide the id of address
$address = 5;

return Inertia::render('Welcome', compact(['options', 'address']));
}

public function store(Request $request)
{
// this will be the id.
$request->input('address');
}

In your VUE component you can now assign the address is to to the form:

const props = defineProps(['address', 'options']);

const form = useForm({ address: props.address });

Multiselect with restrictions

If you want to allow multiple selections, but no more then 3, you can do the following:

<v-select :options="trainerOptions" v-model="form.masterTrainer" :multiple="true" :reduce="(option) => option.id" :selectable="() => form.masterTrainer.length < 3">
</v-select>

Group options

It is currently not possible to group selections: https://github.com/sagalbot/vue-select/issues/342

However, you can do it by a workaround. The workaround is to mix headings and options together like this:

options = [
{ label: "Heading 1 ", heading: true} ,
{ label: "Option A", id: 4, heading: false},
{ label: "Option B", id: 2, heading: false},
{ label: "Heading 2 ", heading: true} ,
{ label: "Option C", id: 8, heading: false},
{ label: "Option D", id: 9, heading: false},
]

You can then fake groups using the template slot and by providing a selectable method:

<v-select :options="options" :reduce="(option) => option.id"  v-model="form.qualification" :selectable="selectableOption">
<template #option="{ label, tag, heading }">
<h5 v-if="heading" class="mb-0">{{ label }}</h5>
<span v-else class="ms-3">{{ label }}</span>
</template>
</v-select>

In addition you need to add the following function:

function selectableOption( option ) { return option.heading != true; }

--

--