161 lines
6.4 KiB
Vue
Executable File
161 lines
6.4 KiB
Vue
Executable File
<template>
|
|
<div>
|
|
<Head>
|
|
<Title>Vue AutoComplete Component</Title>
|
|
<Meta name="description" content="AutoComplete is an input component that provides real-time suggestions when being typed." />
|
|
</Head>
|
|
|
|
<div class="content-section introduction">
|
|
<div class="feature-intro">
|
|
<h1>AutoComplete</h1>
|
|
<p>AutoComplete is an input component that provides real-time suggestions when being typed.</p>
|
|
</div>
|
|
<AppDemoActions />
|
|
</div>
|
|
|
|
<div class="content-section implementation">
|
|
<div class="card">
|
|
<h5>Basic</h5>
|
|
<AutoComplete v-model="selectedCountry1" :suggestions="filteredCountries" @complete="searchCountry($event)" optionLabel="name" />
|
|
|
|
<h5>Grouped</h5>
|
|
<AutoComplete v-model="selectedCity" :suggestions="filteredCities" @complete="searchCity($event)" optionLabel="label" optionGroupLabel="label" optionGroupChildren="items">
|
|
<template #optiongroup="slotProps">
|
|
<div class="flex align-items-center country-item">
|
|
<img src="../../assets/images/flag_placeholder.png" :class="'flag flag-' + slotProps.item.code.toLowerCase()" width="18" />
|
|
<div>{{ slotProps.item.label }}</div>
|
|
</div>
|
|
</template>
|
|
</AutoComplete>
|
|
|
|
<h5>Dropdown, Templating and Force Selection</h5>
|
|
<AutoComplete v-model="selectedCountry2" loadingIcon="pi pi-spinner" :suggestions="filteredCountries" @complete="searchCountry($event)" :dropdown="true" optionLabel="name" forceSelection>
|
|
<template #item="slotProps">
|
|
<div class="country-item">
|
|
<img src="../../assets/images/flag_placeholder.png" :class="'flag flag-' + slotProps.item.code.toLowerCase()" />
|
|
<div>{{ slotProps.item.name }}</div>
|
|
</div>
|
|
</template>
|
|
</AutoComplete>
|
|
|
|
<h5>Virtual Scroll (1000 Items)</h5>
|
|
<AutoComplete v-model="selectedItem" :suggestions="filteredItems" @complete="searchItems" :virtualScrollerOptions="{ itemSize: 38 }" optionLabel="label" dropdown />
|
|
|
|
<h5>Multiple</h5>
|
|
<span class="p-fluid">
|
|
<AutoComplete v-model="selectedCountries" :multiple="true" :suggestions="filteredCountries" @complete="searchCountry($event)" optionLabel="name" />
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<AutoCompleteDoc />
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { FilterMatchMode, FilterService } from 'primevue/api';
|
|
import CountryService from '../../service/CountryService';
|
|
import AutoCompleteDoc from './AutoCompleteDoc';
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
countries: null,
|
|
selectedCountry1: null,
|
|
selectedCountry2: null,
|
|
selectedCity: null,
|
|
filteredCities: null,
|
|
filteredCountries: null,
|
|
selectedCountries: [],
|
|
selectedItem: null,
|
|
filteredItems: null,
|
|
groupedCities: [
|
|
{
|
|
label: 'Germany',
|
|
code: 'DE',
|
|
items: [
|
|
{ label: 'Berlin', value: 'Berlin' },
|
|
{ label: 'Frankfurt', value: 'Frankfurt' },
|
|
{ label: 'Hamburg', value: 'Hamburg' },
|
|
{ label: 'Munich', value: 'Munich' }
|
|
]
|
|
},
|
|
{
|
|
label: 'USA',
|
|
code: 'US',
|
|
items: [
|
|
{ label: 'Chicago', value: 'Chicago' },
|
|
{ label: 'Los Angeles', value: 'Los Angeles' },
|
|
{ label: 'New York', value: 'New York' },
|
|
{ label: 'San Francisco', value: 'San Francisco' }
|
|
]
|
|
},
|
|
{
|
|
label: 'Japan',
|
|
code: 'JP',
|
|
items: [
|
|
{ label: 'Kyoto', value: 'Kyoto' },
|
|
{ label: 'Osaka', value: 'Osaka' },
|
|
{ label: 'Tokyo', value: 'Tokyo' },
|
|
{ label: 'Yokohama', value: 'Yokohama' }
|
|
]
|
|
}
|
|
],
|
|
items: Array.from({ length: 1000 }, (_, i) => ({ label: `Item #${i}`, value: i }))
|
|
};
|
|
},
|
|
countryService: null,
|
|
created() {
|
|
this.countryService = new CountryService();
|
|
},
|
|
mounted() {
|
|
this.countryService.getCountries().then((data) => (this.countries = data));
|
|
},
|
|
methods: {
|
|
searchCountry(event) {
|
|
setTimeout(() => {
|
|
if (!event.query.trim().length) {
|
|
this.filteredCountries = [...this.countries];
|
|
} else {
|
|
this.filteredCountries = this.countries.filter((country) => {
|
|
return country.name.toLowerCase().startsWith(event.query.toLowerCase());
|
|
});
|
|
}
|
|
}, 250);
|
|
},
|
|
searchCity(event) {
|
|
let query = event.query;
|
|
let filteredCities = [];
|
|
|
|
for (let country of this.groupedCities) {
|
|
let filteredItems = FilterService.filter(country.items, ['label'], query, FilterMatchMode.CONTAINS);
|
|
|
|
if (filteredItems && filteredItems.length) {
|
|
filteredCities.push({ ...country, ...{ items: filteredItems } });
|
|
}
|
|
}
|
|
|
|
this.filteredCities = filteredCities;
|
|
},
|
|
searchItems(event) {
|
|
//in a real application, make a request to a remote url with the query and return filtered results, for demo we filter at client side
|
|
let query = event.query;
|
|
let filteredItems = [];
|
|
|
|
for (let i = 0; i < this.items.length; i++) {
|
|
let item = this.items[i];
|
|
|
|
if (item.label.toLowerCase().indexOf(query.toLowerCase()) === 0) {
|
|
filteredItems.push(item);
|
|
}
|
|
}
|
|
|
|
this.filteredItems = filteredItems;
|
|
}
|
|
},
|
|
components: {
|
|
AutoCompleteDoc: AutoCompleteDoc
|
|
}
|
|
};
|
|
</script>
|