Appearance
Autocomplete Component Demo
This page demonstrates the Autocomplete component with various configurations and examples.
Basic Autocomplete
A simple autocomplete with single selection and search functionality.
Code Example
vue
<template>
<OAutoComplete
v-model="selectedCountry"
:items="countries"
placeholder="Search for a country..."
@select="handleSelect"
@search="handleSearch"
/>
</template>
<script setup>
import { ref } from "vue";
const selectedCountry = ref(null);
const countries = ref([
{ text: "Afghanistan", value: "af" },
{ text: "Albania", value: "al" },
{ text: "Algeria", value: "dz" },
{ text: "Argentina", value: "ar" },
{ text: "Australia", value: "au" },
{ text: "Austria", value: "at" },
{ text: "Belgium", value: "be" },
{ text: "Brazil", value: "br" },
{ text: "Canada", value: "ca" },
{ text: "China", value: "cn" },
]);
const handleSelect = (item, value) => {
console.log("Selected:", item, value);
};
const handleSearch = (searchText) => {
console.log("Searching for:", searchText);
};
</script>Demo
Selected: None
Multiple Selection
Autocomplete with multiple selection and chip display.
Code Example
vue
<template>
<OAutoComplete
v-model="selectedFrameworks"
:items="frameworks"
:multiple="true"
placeholder="Select frameworks..."
@select="handleSelect"
@remove="handleRemove"
/>
</template>
<script setup>
import { ref } from "vue";
const selectedFrameworks = ref([]);
const frameworks = ref([
{ text: "React", value: "react" },
{ text: "Vue", value: "vue" },
{ text: "Angular", value: "angular" },
{ text: "Svelte", value: "svelte" },
{ text: "Ember", value: "ember" },
{ text: "Backbone", value: "backbone" },
{ text: "Preact", value: "preact" },
{ text: "Alpine.js", value: "alpine" },
]);
const handleSelect = (item, value) => {
console.log("Selected:", item, value);
};
const handleRemove = (item, value) => {
console.log("Removed:", item, value);
};
</script>Demo
Selected: None
Clearable Input
Autocomplete with a clear button to quickly reset the selection.
Code Example
vue
<template>
<OAutoComplete
v-model="selectedLanguage"
:items="languages"
:clearable="true"
placeholder="Select a programming language..."
/>
</template>
<script setup>
import { ref } from "vue";
const selectedLanguage = ref("react");
const languages = ref([
{ text: "JavaScript", value: "js" },
{ text: "TypeScript", value: "ts" },
{ text: "Python", value: "py" },
{ text: "Java", value: "java" },
{ text: "C++", value: "cpp" },
{ text: "Ruby", value: "rb" },
{ text: "Go", value: "go" },
{ text: "Rust", value: "rust" },
]);
</script>Demo
Selected: react
Selected Items on Top
Keep chosen options at the top of the list for easier management.
Code Example
vue
<template>
<OAutoComplete
v-model="selectedFrameworks"
:items="frameworks"
:multiple="true"
:selected-on-top="true"
placeholder="Select frameworks..."
/>
</template>
<script setup>
import { ref } from "vue";
const selectedFrameworks = ref(["vue", "react"]);
const frameworks = ref([
{ text: "React", value: "react" },
{ text: "Vue", value: "vue" },
{ text: "Angular", value: "angular" },
{ text: "Svelte", value: "svelte" },
{ text: "Ember", value: "ember" },
{ text: "Solid", value: "solid" },
{ text: "Qwik", value: "qwik" },
{ text: "Lit", value: "lit" },
]);
</script>Demo
Selected: vue, react
Loading State
Display a loading spinner while fetching data.
Code Example
vue
<template>
<OAutoComplete
v-model="selectedValue"
:items="items"
:loading="isLoading"
placeholder="Loading options..."
/>
</template>
<script setup>
import { ref } from "vue";
const selectedValue = ref(null);
const items = ref([]);
const isLoading = ref(true);
// Simulate API call
setTimeout(() => {
isLoading.value = false;
items.value = [
{ text: "Apple", value: "apple" },
{ text: "Banana", value: "banana" },
{ text: "Cherry", value: "cherry" },
{ text: "Date", value: "date" },
{ text: "Elderberry", value: "elderberry" },
];
}, 2000);
</script>Demo
Selected: None
Async Search
Perform asynchronous searches as the user types.
Code Example
vue
<template>
<OAutoComplete
v-model="selectedUser"
:items="users"
:loading="loading"
placeholder="Search for a user (type at least 2 characters)..."
@search="handleSearch"
/>
</template>
<script setup>
import { ref } from "vue";
const selectedUser = ref(null);
const users = ref([]);
const loading = ref(false);
const handleSearch = (searchText) => {
if (!searchText || searchText.length < 2) {
users.value = [];
return;
}
loading.value = true;
// Simulate API call
setTimeout(() => {
const allUsers = [
{ text: "John Doe", value: "john" },
{ text: "Jane Smith", value: "jane" },
{ text: "Bob Johnson", value: "bob" },
{ text: "Alice Williams", value: "alice" },
{ text: "Charlie Brown", value: "charlie" },
];
users.value = allUsers.filter((user) =>
user.text.toLowerCase().includes(searchText.toLowerCase())
);
loading.value = false;
}, 500);
};
</script>Demo
Selected: None
Custom Filter Function
Use a custom filter function to search across multiple properties.
Code Example
vue
<template>
<OAutoComplete
v-model="selectedProducts"
:items="products"
:multiple="true"
:filter-function="customFilter"
placeholder="Search by product name or category..."
/>
</template>
<script setup>
import { ref } from "vue";
const selectedProducts = ref([]);
const products = ref([
{ text: "Apple MacBook Pro", value: "mbp", category: "laptop" },
{ text: "Apple iPhone 15", value: "iphone15", category: "phone" },
{ text: "Apple iPad Air", value: "ipad", category: "tablet" },
{ text: "Samsung Galaxy S24", value: "s24", category: "phone" },
{ text: "Samsung Galaxy Book", value: "book", category: "laptop" },
{ text: "Dell XPS 13", value: "xps", category: "laptop" },
{ text: "Microsoft Surface Pro", value: "surface", category: "tablet" },
]);
const customFilter = (item, searchText) => {
const text = item.text.toLowerCase();
const category = item.category.toLowerCase();
const search = searchText.toLowerCase();
// Search in both text and category
return text.includes(search) || category.includes(search);
};
</script>Demo
Selected: None
Disabled State
Autocomplete in disabled state.
Code Example
vue
<template>
<OAutoComplete
v-model="selectedValue"
:items="items"
:disabled="true"
placeholder="This field is disabled"
/>
</template>
<script setup>
import { ref } from "vue";
const selectedValue = ref("option1");
const items = ref([
{ text: "Option 1", value: "option1" },
{ text: "Option 2", value: "option2" },
{ text: "Option 3", value: "option3" },
]);
</script>Demo
Selected: option1
Readonly State
Autocomplete in readonly state.
Code Example
vue
<template>
<OAutoComplete
v-model="selectedValue"
:items="items"
:readonly="true"
placeholder="This field is readonly"
/>
</template>
<script setup>
import { ref } from "vue";
const selectedValue = ref("read");
const items = ref([
{ text: "Readonly Value", value: "read" },
{ text: "Another Value", value: "another" },
]);
</script>Demo
Selected: read
Different Placements
Autocomplete with various placement options.
Code Example
vue
<template>
<div class="placement-examples">
<OAutoComplete
v-model="selectedValue"
:items="items"
placement="bottom"
placeholder="Bottom (default)"
/>
<OAutoComplete
v-model="selectedValue"
:items="items"
placement="top"
placeholder="Top"
/>
</div>
</template>
<script setup>
import { ref } from "vue";
const selectedValue = ref(null);
const items = ref([
{ text: "Option 1", value: "opt1" },
{ text: "Option 2", value: "opt2" },
{ text: "Option 3", value: "opt3" },
]);
</script>
<style scoped>
.placement-examples {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
padding: 4rem 2rem;
}
</style>Demo
Custom Width
Autocomplete with custom menu width.
Code Example
vue
<template>
<div class="width-examples">
<OAutoComplete
v-model="selectedValue"
:items="items"
placeholder="Default width (matches trigger)"
/>
<OAutoComplete
v-model="selectedValue"
:items="items"
:menu-width="400"
placeholder="Custom width (400px)"
/>
</div>
</template>
<script setup>
import { ref } from "vue";
const selectedValue = ref(null);
const items = ref([
{ text: "Short", value: "short" },
{ text: "Medium length option", value: "medium" },
{
text: "Very long option text that might overflow in smaller containers",
value: "long",
},
]);
</script>Demo
Selected: None
Form Integration
Autocomplete integrated into a form with validation.
Code Example
vue
<template>
<form @submit.prevent="submitForm" class="form-example">
<div class="form-group">
<label>Username</label>
<OAutoComplete
v-model="formData.username"
:items="usernames"
placeholder="Search for a username..."
/>
<span v-if="formErrors.username" class="error">{{
formErrors.username
}}</span>
</div>
<div class="form-group">
<label>Skills</label>
<OAutoComplete
v-model="formData.skills"
:items="skills"
:multiple="true"
placeholder="Select your skills..."
/>
<span v-if="formErrors.skills" class="error">{{
formErrors.skills
}}</span>
</div>
<div class="form-group">
<label>Country</label>
<OAutoComplete
v-model="formData.country"
:items="countries"
:clearable="true"
placeholder="Search for your country..."
/>
<span v-if="formErrors.country" class="error">{{
formErrors.country
}}</span>
</div>
<div class="form-actions">
<button type="submit" class="submit-btn">Submit Form</button>
<button type="button" @click="validateForm" class="validate-btn">
Validate Only
</button>
</div>
</form>
</template>
<script setup>
import { reactive, ref } from "vue";
const formData = reactive({
username: null,
skills: [],
country: null,
});
const formErrors = reactive({
username: "",
skills: "",
country: "",
});
const usernames = ref([
{ text: "john_doe", value: "john" },
{ text: "jane_smith", value: "jane" },
{ text: "bob_wilson", value: "bob" },
{ text: "alice_wonder", value: "alice" },
]);
const skills = ref([
{ text: "JavaScript", value: "js" },
{ text: "TypeScript", value: "ts" },
{ text: "Vue.js", value: "vue" },
{ text: "React", value: "react" },
{ text: "Node.js", value: "node" },
{ text: "Python", value: "python" },
{ text: "Docker", value: "docker" },
{ text: "Kubernetes", value: "k8s" },
]);
const countries = ref([
{ text: "United States", value: "us" },
{ text: "United Kingdom", value: "uk" },
{ text: "Canada", value: "ca" },
{ text: "Australia", value: "au" },
{ text: "Germany", value: "de" },
{ text: "France", value: "fr" },
{ text: "Japan", value: "jp" },
{ text: "India", value: "in" },
]);
const validateForm = () => {
formErrors.username = !formData.username ? "Username is required" : "";
formErrors.skills =
formData.skills.length === 0 ? "At least one skill is required" : "";
formErrors.country = !formData.country ? "Country is required" : "";
};
const submitForm = () => {
validateForm();
if (!formErrors.username && !formErrors.skills && !formErrors.country) {
console.log("Form submitted:", formData);
alert("Form submitted successfully!");
}
};
</script>
<style scoped>
.form-example {
max-width: 500px;
padding: 1.5rem;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
background: #fafafa;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
color: #374151;
}
.error {
color: #ef4444;
font-size: 0.875rem;
margin-top: 0.25rem;
display: block;
}
.form-actions {
display: flex;
gap: 0.75rem;
margin-top: 1.5rem;
}
.submit-btn,
.validate-btn {
padding: 0.625rem 1.25rem;
border: none;
border-radius: 0.375rem;
cursor: pointer;
font-weight: 500;
transition: all 0.2s;
}
.submit-btn {
background: #3b82f6;
color: white;
}
.submit-btn:hover {
background: #2563eb;
}
.validate-btn {
background: #6b7280;
color: white;
}
.validate-btn:hover {
background: #4b5563;
}
</style>