I have the following simple setup, with a client-side javascript app using Vue 3:
HTML (with a select box):
<html>
<head>
<title>Test</title>
</head>
<body>
<div id="vuetest">
<select id="assignment-select" v-model="ft_assignment">
<optgroup v-for="optgroup in ft_assignments" :label="optgroup.text">
<option
v-for="option in optgroup.children"
:value="option.id"
:disabled="option.disabled"
>
{{ option.text }}
</option>
</optgroup>
</select>
</div>
<script type="module">
import { createApp } from "https://unpkg.com/vue@3/dist/vue.esm-browser.js";
const app = createApp({
data() {
return {
ft_assignment: "a",
ft_assignments: [
{
text: "hi",
children: [
{ id: "a", text: "a1" },
{ id: "b", text: "b1" },
],
},
{
text: "there",
children: [
{ id: "c", text: "c1" },
{ id: "d", text: "d1" },
],
},
],
};
},
watch: {
ft_assignment(v) {
console.log(v);
},
},
}).mount("#vuetest");
</script>
</body>
</html>
I would like to use a "nice" select box (e.g. vue-select or select2) with modern features like searching, etc. - but I can't work out how to include the relevant components. I see many warnings of mixing jQuery and Vue.js, so I am avoiding just including select2 as a jquery plugin and rendering it that way.
How can I turn the select box into a "nicer" more modern select element?
This is not using esm build of vue 3, but this still uses UMD build which is supported directly in the browser (the reason is because vue-select library doesn't provide the esm build version, but it still supports UMD build).
Basically include the dependencies this way:
<script src="https://unpkg.com/vue@latest"></script>
<script src="https://unpkg.com/vue-select@beta"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-select@latest/dist/vue-select.css" />
Then import the vue
this way:
const { createApp } = Vue;
Then import the vue-select
component this way:
const app = createApp({
components: {
vSelect: window["vue-select"],
},
...
Working code snippet:
<html>
<head>
<title>Test</title>
<script src="https://unpkg.com/vue@latest"></script>
<script src="https://unpkg.com/vue-select@beta"></script>
<link
rel="stylesheet"
href="https://unpkg.com/vue-select@latest/dist/vue-select.css"
/>
</head>
<body>
<div id="vuetest">
<v-select :options="flattenedFtAssignemnts" label="text"></v-select>
</div>
<script type="module">
const { createApp } = Vue;
const app = createApp({
components: {
vSelect: window["vue-select"],
},
data() {
return {
ft_assignment: "a",
ft_assignments: [
{
text: "hi",
children: [
{ id: "a", text: "a1" },
{ id: "b", text: "b1" },
],
},
{
text: "there",
children: [
{ id: "c", text: "c1" },
{ id: "d", text: "d1" },
],
},
],
};
},
computed: {
flattenedFtAssignemnts() {
return this.ft_assignments.map(obj => obj.children).flat();
}
},
watch: {
ft_assignment(v) {
console.log(v);
},
},
});
app.mount("#vuetest");
</script>
</body>
</html>
Unfortunately vue-select
currently doesn't support <optgroup>
, so I had to flatten the children for select.