How to use type-a-head in vue3
With vue-select package
You can do it like this in the vue-select package
<template>
<vSelect v-model="selectedValue" :noDrop="searchInput === ''" :filterable="false" :options="options" class="bg-white" @search="searching" />
</template>
<script setup>
import vSelect from 'vue-select'
import {ref} from "vue";
import axios from 'axios';
import { debounce } from "lodash";
import "vue-select/dist/vue-select.css";
const options = ref([]);
const searchInput = ref('');
const selectedValue = ref(null);
const searching = debounce( async function (search, loading) {
loading(true);
searchInput.value = search;
axios.post('/dashboard/users/search', {key: search.trim()})
.then(response => {
options.value = response.data;
})
.catch(error => {
console.error(error);
})
.finally(() => {
loading(false);
});
}, 200);
</script>
<style scoped>
:deep(.vs__search::placeholder ){
color: rgba(0, 0, 0, 0.4);
}
</style>
I used
:noDrop="searchInput === ''"
because otherwise, you would get a "Nothing found" message when you first enter the select box (and your ajax call is not returning.
I also had to disable filtering like this:
:filterable="false"
Because otherwise, it would search in local search results. Since I can't display all search results at once (have to limit them on the backend, becaue ther are soo many results), it would happen, then when you enter slowly a name, it could be that you get a "not found" inbetween.
The debounce is used to not trigger an ajax request on every keystore. The scoped style is used because I am using Tailwind and it was breaking the placeholder layout.
With Vue Multiselect
This is same thing used in VueMultiselect. Exact same resons as above for internal-search, debounce, and showNoOptions..
<template>
<VueMultiselect
v-model="selected"
:options="options"
:multiple="false"
:searchable="true"
@search-change="asyncFind"
label="label"
track-by="value"
:loading="loading"
:internal-search="false"
:showNoOptions="selected !== null || loading"
>
<template #noResult>
<span v-if="!loading">
No user found
</span>
<span v-else>
Loading...
</span>
</template>
</VueMultiselect>
</template>
<script setup>
import VueMultiselect from 'vue-multiselect'
import axios from "axios";
import {ref} from "vue";
import { debounce } from "lodash";
const selected = ref(null);
const options = ref([]);
const loading = ref(false);
const asyncFind = debounce( async function (query) {
loading.value = true;
axios.post('/dashboard/users/search', {key: query.trim()})
.then(response => {
options.value = response.data;
})
.catch(error => {
console.error(error);
})
.finally(() => {
loading.value = false;
});
}, 500);
</script>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
<style scoped>
:deep(input[type='text']:focus) {
outline: none;
--tw-ring-offset-width: 0;
--tw-ring-color: transparent;
--tw-ring-offset-color: transparent;
--tw-ring-shadow: none;
--tw-ring-offset-shadow: none;
box-shadow: none;
border-color: initial;
}
</style>
``