Refactor #1451 - For Dropdown
parent
efc8b36523
commit
1ac34d77ca
|
@ -14,6 +14,7 @@ let globalDependencies = {
|
|||
'primevue/utils': 'primevue.utils',
|
||||
'primevue/button': 'primevue.button',
|
||||
'primevue/inputtext': 'primevue.inputtext',
|
||||
'primevue/virtualscroller': 'primevue.virtualscroller',
|
||||
'primevue/dialog': 'primevue.dialog',
|
||||
'primevue/paginator': 'primevue.paginator',
|
||||
'primevue/confirmationeventbus': 'primevue.confirmationeventbus',
|
||||
|
@ -129,4 +130,4 @@ addUtils();
|
|||
addApi();
|
||||
addServices();
|
||||
|
||||
export default entries;
|
||||
export default entries;
|
||||
|
|
|
@ -23,32 +23,36 @@
|
|||
<span class="p-dropdown-filter-icon pi pi-search"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div :ref="itemsWrapperRef" class="p-dropdown-items-wrapper" :style="{'max-height': scrollHeight}">
|
||||
<ul class="p-dropdown-items" role="listbox">
|
||||
<template v-if="!optionGroupLabel">
|
||||
<li v-for="(option, i) of visibleOptions" :class="['p-dropdown-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
|
||||
:key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)">
|
||||
<slot name="option" :option="option" :index="i">{{getOptionLabel(option)}}</slot>
|
||||
</li>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-for="(optionGroup, i) of visibleOptions" :key="getOptionGroupRenderKey(optionGroup)">
|
||||
<li class="p-dropdown-item-group" >
|
||||
<slot name="optiongroup" :option="optionGroup" :index="i">{{getOptionGroupLabel(optionGroup)}}</slot>
|
||||
<div :ref="itemsWrapperRef" class="p-dropdown-items-wrapper" :style="{'max-height': virtualScrollerDisabled ? scrollHeight : ''}">
|
||||
<VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :items="visibleOptions" :style="{'height': scrollHeight}" :disabled="virtualScrollerDisabled">
|
||||
<template v-slot:content="{ styleClass, contentRef, items, getItemOptions }">
|
||||
<ul :ref="contentRef" :class="['p-dropdown-items', styleClass]" role="listbox">
|
||||
<template v-if="!optionGroupLabel">
|
||||
<li v-for="(option, i) of getVisibleOptions(items)" :class="['p-dropdown-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
|
||||
:key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)">
|
||||
<slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{getOptionLabel(option)}}</slot>
|
||||
</li>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-for="(optionGroup, i) of getVisibleOptions(items)" :key="getOptionGroupRenderKey(optionGroup)">
|
||||
<li class="p-dropdown-item-group">
|
||||
<slot name="optiongroup" :option="optionGroup" :index="getOptionIndex(i, getItemOptions)">{{getOptionGroupLabel(optionGroup)}}</slot>
|
||||
</li>
|
||||
<li v-for="(option, i) of getOptionGroupChildren(optionGroup)" :class="['p-dropdown-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
|
||||
:key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)">
|
||||
<slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{getOptionLabel(option)}}</slot>
|
||||
</li>
|
||||
</template>
|
||||
</template>
|
||||
<li v-if="filterValue && (!getVisibleOptions(items) || (getVisibleOptions(items) && getVisibleOptions(items).length === 0))" class="p-dropdown-empty-message">
|
||||
<slot name="emptyfilter">{{emptyFilterMessageText}}</slot>
|
||||
</li>
|
||||
<li v-for="(option, i) of getOptionGroupChildren(optionGroup)" :class="['p-dropdown-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
|
||||
:key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)">
|
||||
<slot name="option" :option="option" :index="i">{{getOptionLabel(option)}}</slot>
|
||||
<li v-else-if="(!options || (options && options.length === 0))" class="p-dropdown-empty-message">
|
||||
<slot name="empty">{{emptyMessageText}}</slot>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</template>
|
||||
<li v-if="filterValue && (!visibleOptions || (visibleOptions && visibleOptions.length === 0))" class="p-dropdown-empty-message">
|
||||
<slot name="emptyfilter">{{emptyFilterMessageText}}</slot>
|
||||
</li>
|
||||
<li v-else-if="(!options || (options && options.length === 0))" class="p-dropdown-empty-message">
|
||||
<slot name="empty">{{emptyMessageText}}</slot>
|
||||
</li>
|
||||
</ul>
|
||||
</VirtualScroller>
|
||||
</div>
|
||||
<slot name="footer" :value="modelValue" :options="visibleOptions"></slot>
|
||||
</div>
|
||||
|
@ -62,6 +66,7 @@ import {ConnectedOverlayScrollHandler,ObjectUtils,DomHandler,ZIndexUtils} from '
|
|||
import OverlayEventBus from 'primevue/overlayeventbus';
|
||||
import {FilterService} from 'primevue/api';
|
||||
import Ripple from 'primevue/ripple';
|
||||
import VirtualScroller from 'primevue/virtualscroller';
|
||||
|
||||
export default {
|
||||
name: 'Dropdown',
|
||||
|
@ -117,6 +122,10 @@ export default {
|
|||
loadingIcon: {
|
||||
type: String,
|
||||
default: 'pi pi-spinner pi-spin'
|
||||
},
|
||||
virtualScrollerOptions: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@ -135,6 +144,7 @@ export default {
|
|||
searchValue: null,
|
||||
overlay: null,
|
||||
itemsWrapper: null,
|
||||
virtualScroller: null,
|
||||
beforeUnmount() {
|
||||
this.unbindOutsideClickListener();
|
||||
this.unbindResizeListener();
|
||||
|
@ -152,6 +162,12 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
getVisibleOptions(items) {
|
||||
return items || this.visibleOptions;
|
||||
},
|
||||
getOptionIndex(index, fn) {
|
||||
return this.virtualScrollerDisabled ? index : (fn && fn(index)['index']);
|
||||
},
|
||||
getOptionLabel(option) {
|
||||
return this.optionLabel ? ObjectUtils.resolveFieldData(option, this.optionLabel) : option;
|
||||
},
|
||||
|
@ -415,6 +431,13 @@ export default {
|
|||
this.$refs.filterInput.focus();
|
||||
}
|
||||
|
||||
if (!this.virtualScrollerDisabled) {
|
||||
const selectedIndex = this.getSelectedOptionIndex();
|
||||
if (selectedIndex !== -1) {
|
||||
this.virtualScroller.scrollToIndex(selectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
this.$emit('show');
|
||||
},
|
||||
onOverlayLeave() {
|
||||
|
@ -581,6 +604,9 @@ export default {
|
|||
itemsWrapperRef(el) {
|
||||
this.itemsWrapper = el;
|
||||
},
|
||||
virtualScrollerRef(el) {
|
||||
this.virtualScroller = el;
|
||||
},
|
||||
scrollValueInView() {
|
||||
if (this.overlay) {
|
||||
let selectedItem = DomHandler.findSingle(this.overlay, 'li.p-highlight');
|
||||
|
@ -675,6 +701,9 @@ export default {
|
|||
appendDisabled() {
|
||||
return this.appendTo === 'self';
|
||||
},
|
||||
virtualScrollerDisabled() {
|
||||
return !this.virtualScrollerOptions;
|
||||
},
|
||||
appendTarget() {
|
||||
return this.appendDisabled ? null : this.appendTo;
|
||||
},
|
||||
|
@ -684,6 +713,9 @@ export default {
|
|||
},
|
||||
directives: {
|
||||
'ripple': Ripple
|
||||
},
|
||||
components: {
|
||||
'VirtualScroller': VirtualScroller
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -47,6 +47,9 @@
|
|||
|
||||
<h5>Loading State</h5>
|
||||
<Dropdown placeholder="Loading..." loading></Dropdown>
|
||||
|
||||
<h5>Virtual Scroll (100000 Items)</h5>
|
||||
<Dropdown v-model="selectedItem" :options="items" optionLabel="label" optionValue="value" :virtualScrollerOptions="{ itemSize: 31 }" placeholder="Select Item"></Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -64,6 +67,7 @@ export default {
|
|||
selectedCity2: null,
|
||||
selectedCountry: null,
|
||||
selectedGroupedCity: null,
|
||||
selectedItem: null,
|
||||
cities: [
|
||||
{name: 'New York', code: 'NY'},
|
||||
{name: 'Rome', code: 'RM'},
|
||||
|
@ -84,7 +88,7 @@ export default {
|
|||
{name: 'United States', code: 'US'}
|
||||
],
|
||||
groupedCities: [{
|
||||
label: 'Germany', code: 'DE',
|
||||
label: 'Germany', code: 'DE',
|
||||
items: [
|
||||
{label: 'Berlin', value: 'Berlin'},
|
||||
{label: 'Frankfurt', value: 'Frankfurt'},
|
||||
|
@ -93,7 +97,7 @@ export default {
|
|||
]
|
||||
},
|
||||
{
|
||||
label: 'USA', code: 'US',
|
||||
label: 'USA', code: 'US',
|
||||
items: [
|
||||
{label: 'Chicago', value: 'Chicago'},
|
||||
{label: 'Los Angeles', value: 'Los Angeles'},
|
||||
|
@ -102,14 +106,15 @@ export default {
|
|||
]
|
||||
},
|
||||
{
|
||||
label: 'Japan', code: 'JP',
|
||||
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: 100000 }, (_, i) => ({ label: `Item #${i}`, value: i }))
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const path = require('path');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
publicPath: process.env.NODE_ENV === 'production' ? '/primevue/showcase/' : '/',
|
||||
|
@ -24,7 +24,8 @@ module.exports = {
|
|||
'primevue/confirmationeventbus': path.resolve(__dirname, 'src/components/confirmationeventbus/ConfirmationEventBus.js'),
|
||||
'primevue/toasteventbus': path.resolve(__dirname, 'src/components/toasteventbus/ToastEventBus.js'),
|
||||
'primevue/overlayeventbus': path.resolve(__dirname, 'src/components/overlayeventbus/OverlayEventBus.js'),
|
||||
'primevue/terminalservice': path.resolve(__dirname, 'src/components/terminalservice/TerminalService.js')
|
||||
'primevue/terminalservice': path.resolve(__dirname, 'src/components/terminalservice/TerminalService.js'),
|
||||
'primevue/virtualscroller': path.resolve(__dirname, 'src/components/virtualscroller/VirtualScroller.vue')
|
||||
},
|
||||
},
|
||||
output: {
|
||||
|
@ -34,4 +35,4 @@ module.exports = {
|
|||
css: {
|
||||
extract: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue