Refactor #1451 - For Listbox
parent
47edaea7ad
commit
ba75e9c51c
|
@ -1,4 +1,5 @@
|
||||||
import { VNode } from 'vue';
|
import { VNode } from 'vue';
|
||||||
|
import { VirtualScrollerProps } from '../virtualscroller';
|
||||||
|
|
||||||
interface ListboxProps {
|
interface ListboxProps {
|
||||||
modelValue?: any;
|
modelValue?: any;
|
||||||
|
@ -20,6 +21,7 @@ interface ListboxProps {
|
||||||
filterFields?: string[];
|
filterFields?: string[];
|
||||||
emptyFilterMessage?: string;
|
emptyFilterMessage?: string;
|
||||||
emptyMessage?: string;
|
emptyMessage?: string;
|
||||||
|
virtualScrollerOptions?: VirtualScrollerProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare class Listbox {
|
declare class Listbox {
|
||||||
|
|
|
@ -8,31 +8,38 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-listbox-list-wrapper" :style="listStyle">
|
<div class="p-listbox-list-wrapper" :style="listStyle">
|
||||||
<ul class="p-listbox-list" role="listbox" aria-multiselectable="multiple">
|
<VirtualScroller :ref="virtualScrollerRef" v-bind="virtualScrollerOptions" :style="listStyle" :items="visibleOptions" :disabled="virtualScrollerDisabled">
|
||||||
<template v-if="!optionGroupLabel">
|
<template v-slot:content="{ styleClass, contentRef, items, getItemOptions }">
|
||||||
<li v-for="(option, i) of visibleOptions" :tabindex="isOptionDisabled(option) ? null : '0'" :class="['p-listbox-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
|
<ul :ref="contentRef" :class="['p-listbox-list', styleClass]" role="listbox" aria-multiselectable="multiple">
|
||||||
:key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" @touchend="onOptionTouchEnd()" @keydown="onOptionKeyDown($event, option)" role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)" >
|
<template v-if="!optionGroupLabel">
|
||||||
<slot name="option" :option="option" :index="i">{{getOptionLabel(option)}} </slot>
|
<li v-for="(option, i) of getVisibleOptions(items)" :tabindex="isOptionDisabled(option) ? null : '0'" :class="['p-listbox-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
|
||||||
</li>
|
:key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" @touchend="onOptionTouchEnd()" @keydown="onOptionKeyDown($event, option)" role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)" >
|
||||||
</template>
|
<slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">{{getOptionLabel(option)}} </slot>
|
||||||
<template v-else>
|
</li>
|
||||||
<template v-for="(optionGroup, i) of visibleOptions" :key="getOptionGroupRenderKey(optionGroup)">
|
</template>
|
||||||
<li class="p-listbox-item-group" >
|
<template v-else>
|
||||||
<slot name="optiongroup" :option="optionGroup" :index="i">{{getOptionGroupLabel(optionGroup)}}</slot>
|
<template v-for="(optionGroup, i) of getVisibleOptions(items)" :key="getOptionGroupRenderKey(optionGroup)">
|
||||||
|
<li class="p-listbox-item-group">
|
||||||
|
<slot name="optiongroup" :option="optionGroup" :index="getOptionIndex(i, getItemOptions)">{{getOptionGroupLabel(optionGroup)}}</slot>
|
||||||
|
</li>
|
||||||
|
<li v-for="(option, i) of getOptionGroupChildren(optionGroup)" :tabindex="isOptionDisabled(option) ? null : '0'" :class="['p-listbox-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
|
||||||
|
:key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" @touchend="onOptionTouchEnd()" @keydown="onOptionKeyDown($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-listbox-empty-message">
|
||||||
|
<slot name="emptyfilter">{{emptyFilterMessageText}}</slot>
|
||||||
</li>
|
</li>
|
||||||
<li v-for="(option, i) of getOptionGroupChildren(optionGroup)" :tabindex="isOptionDisabled(option) ? null : '0'" :class="['p-listbox-item', {'p-highlight': isSelected(option), 'p-disabled': isOptionDisabled(option)}]" v-ripple
|
<li v-else-if="(!options || (options && options.length === 0))" class="p-listbox-empty-message">
|
||||||
:key="getOptionRenderKey(option)" @click="onOptionSelect($event, option)" @touchend="onOptionTouchEnd()" @keydown="onOptionKeyDown($event, option)" role="option" :aria-label="getOptionLabel(option)" :aria-selected="isSelected(option)" >
|
<slot name="empty">{{emptyMessageText}}</slot>
|
||||||
<slot name="option" :option="option" :index="i">{{getOptionLabel(option)}}</slot>
|
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
<li v-if="filterValue && (!visibleOptions || (visibleOptions && visibleOptions.length === 0))" class="p-listbox-empty-message">
|
<template v-slot:loader="{ options }" v-if="$slots.loader">
|
||||||
<slot name="emptyfilter">{{emptyFilterMessageText}}</slot>
|
<slot name="loader" :options="options"></slot>
|
||||||
</li>
|
</template>
|
||||||
<li v-else-if="(!options || (options && options.length === 0))" class="p-listbox-empty-message">
|
</VirtualScroller>
|
||||||
<slot name="empty">{{emptyMessageText}}</slot>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
<slot name="footer" :value="modelValue" :options="visibleOptions"></slot>
|
<slot name="footer" :value="modelValue" :options="visibleOptions"></slot>
|
||||||
</div>
|
</div>
|
||||||
|
@ -43,6 +50,7 @@ import {ObjectUtils} from 'primevue/utils';
|
||||||
import {DomHandler} from 'primevue/utils';
|
import {DomHandler} from 'primevue/utils';
|
||||||
import {FilterService} from 'primevue/api';
|
import {FilterService} from 'primevue/api';
|
||||||
import Ripple from 'primevue/ripple';
|
import Ripple from 'primevue/ripple';
|
||||||
|
import VirtualScroller from 'primevue/virtualscroller';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Listbox',
|
name: 'Listbox',
|
||||||
|
@ -78,15 +86,26 @@ export default {
|
||||||
emptyMessage: {
|
emptyMessage: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null
|
||||||
|
},
|
||||||
|
virtualScrollerOptions: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
optionTouched: false,
|
optionTouched: false,
|
||||||
|
virtualScroller: null,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
filterValue: null
|
filterValue: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getVisibleOptions(items) {
|
||||||
|
return items || this.visibleOptions;
|
||||||
|
},
|
||||||
|
getOptionIndex(index, fn) {
|
||||||
|
return this.virtualScrollerDisabled ? index : (fn && fn(index)['index']);
|
||||||
|
},
|
||||||
getOptionLabel(option) {
|
getOptionLabel(option) {
|
||||||
return this.optionLabel ? ObjectUtils.resolveFieldData(option, this.optionLabel) : option;
|
return this.optionLabel ? ObjectUtils.resolveFieldData(option, this.optionLabel) : option;
|
||||||
},
|
},
|
||||||
|
@ -268,6 +287,9 @@ export default {
|
||||||
},
|
},
|
||||||
onFilterChange(event) {
|
onFilterChange(event) {
|
||||||
this.$emit('filter', {originalEvent: event, value: event.target.value});
|
this.$emit('filter', {originalEvent: event, value: event.target.value});
|
||||||
|
},
|
||||||
|
virtualScrollerRef(el) {
|
||||||
|
this.virtualScroller = el;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -302,10 +324,16 @@ export default {
|
||||||
},
|
},
|
||||||
emptyMessageText() {
|
emptyMessageText() {
|
||||||
return this.emptyMessage || this.$primevue.config.locale.emptyMessage;
|
return this.emptyMessage || this.$primevue.config.locale.emptyMessage;
|
||||||
|
},
|
||||||
|
virtualScrollerDisabled() {
|
||||||
|
return !this.virtualScrollerOptions;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
'ripple': Ripple
|
'ripple': Ripple
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
'VirtualScroller': VirtualScroller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue