Refactor #3832 Refactor #3833 - For MultiSelect

pull/3841/head
Tuğçe Küçükoğlu 2023-04-04 15:41:18 +03:00
parent 01fe1466a6
commit c1c9953939
3 changed files with 129 additions and 33 deletions

View File

@ -182,9 +182,39 @@ const MultiSelectProps = [
{ {
name: 'loadingIcon', name: 'loadingIcon',
type: 'string', type: 'string',
default: 'pi pi-spinner pi-spin', default: 'null',
description: 'Icon to display in loading state.' description: 'Icon to display in loading state.'
}, },
{
name: 'checkboxIcon',
type: 'string',
default: 'null',
description: 'Icon to display in the checkboxes.'
},
{
name: 'closeIcon',
type: 'string',
default: 'null',
description: 'Icon to display in the dropdown close button.'
},
{
name: 'dropdownIcon',
type: 'string',
default: 'null',
description: 'Icon to display in the dropdown.'
},
{
name: 'filterIcon',
type: 'string',
default: 'null',
description: 'Icon to display in filter input.'
},
{
name: 'removeTokenIcon',
type: 'string',
default: 'null',
description: 'Icon to display in chip remove action.'
},
{ {
name: 'selectAll', name: 'selectAll',
type: 'boolean', type: 'boolean',
@ -357,7 +387,7 @@ const MultiSelectEvents = [
const MultiSelectSlots = [ const MultiSelectSlots = [
{ {
name: 'value', name: 'value',
description: 'Custom content for the item value' description: 'Custom content for the item value.'
}, },
{ {
name: 'chip', name: 'chip',
@ -365,39 +395,59 @@ const MultiSelectSlots = [
}, },
{ {
name: 'indicator', name: 'indicator',
description: 'Custom content for the dropdown indicator' description: 'Custom content for the dropdown indicator.'
}, },
{ {
name: 'header', name: 'header',
description: "Custom content for the component's header" description: "Custom content for the component's header."
}, },
{ {
name: 'footer', name: 'footer',
description: "Custom content for the component's footer" description: "Custom content for the component's footer."
}, },
{ {
name: 'option', name: 'option',
description: "Custom content for the item's option" description: "Custom content for the item's option."
}, },
{ {
name: 'optiongroup', name: 'optiongroup',
description: "Custom content for the item's optiongroup" description: "Custom content for the item's optiongroup."
}, },
{ {
name: 'emptyfilter', name: 'emptyfilter',
description: 'Custom content when there is no filtered data to display' description: 'Custom content when there is no filtered data to display.'
}, },
{ {
name: 'empty', name: 'empty',
description: 'Custom content when there is no data to display' description: 'Custom content when there is no data to display.'
}, },
{ {
name: 'content', name: 'content',
description: 'Custom content for the virtual scroller' description: 'Custom content for the virtual scroller.'
}, },
{ {
name: 'loader', name: 'loader',
description: 'Custom content for the virtual scroller loader items' description: 'Custom content for the virtual scroller loader items.'
},
{
name: 'removetokenicon',
description: 'Custom remove token icon template.'
},
{
name: 'headercheckboxicon',
description: 'Custom header checkbox icon template.'
},
{
name: 'filtericon',
description: 'Custom filter icon template.'
},
{
name: 'closeicon',
description: 'Custom close icon template.'
},
{
name: 'itemcheckboxicon',
description: 'Custom item checkbox icon template.'
} }
]; ];

View File

@ -191,32 +191,26 @@ export interface MultiSelectProps {
loading?: boolean | undefined; loading?: boolean | undefined;
/** /**
* Icon to display in the checkboxes. * Icon to display in the checkboxes.
* @defaultValue pi pi-check
*/ */
checkboxIcon?: string | undefined; checkboxIcon?: string | undefined;
/** /**
* Icon to display in the dropdown close button. * Icon to display in the dropdown close button.
* @defaultValue pi pi-times
*/ */
closeIcon?: string | undefined; closeIcon?: string | undefined;
/** /**
* Icon to display in the dropdown. * Icon to display in the dropdown.
* @defaultValue pi pi-chevron-down
*/ */
dropdownIcon?: string | undefined; dropdownIcon?: string | undefined;
/** /**
* Icon to display in filter input. * Icon to display in filter input.
* @defaultValue pi pi-search
*/ */
filterIcon?: string | undefined; filterIcon?: string | undefined;
/** /**
* Icon to display in loading state. * Icon to display in loading state.
* @defaultValue pi pi-spinner pi-spin
*/ */
loadingIcon?: string | undefined; loadingIcon?: string | undefined;
/** /**
* Icon to display in chip remove action. * Icon to display in chip remove action.
* @defaultValue pi pi-times-circle
*/ */
removeTokenIcon?: string | undefined; removeTokenIcon?: string | undefined;
/** /**
@ -414,6 +408,38 @@ export interface MultiSelectSlots {
*/ */
options: any[]; options: any[];
}): VNode[]; }): VNode[];
/**
* Custom remove token icon template.
*/
removetokenicon(): VNode[];
/**
* Custom header checkbox icon template.
* @param {Object} scope - header checkbox icon slot's params.
*/
headercheckboxicon(scope: {
/**
* Options of the loader items for virtualscroller
*/
allSelected: boolean;
}): VNode[];
/**
* Custom filter icon template.
*/
filtericon(): VNode[];
/**
* Custom close icon template.
*/
closeicon(): VNode[];
/**
* Custom item checkbox icon template.
* @param {Object} scope - header checkbox icon slot's params.
*/
itemcheckboxicon(scope: {
/**
* Options of the loader items for virtualscroller
*/
selected: boolean;
}): VNode[];
} }
/** /**

View File

@ -33,7 +33,9 @@
<slot name="chip" :value="item"> <slot name="chip" :value="item">
<span class="p-multiselect-token-label">{{ getLabelByValue(item) }}</span> <span class="p-multiselect-token-label">{{ getLabelByValue(item) }}</span>
</slot> </slot>
<span v-if="!disabled" :class="['p-multiselect-token-icon', removeTokenIcon]" @click.stop="removeOption($event, item)"></span> <slot v-if="!disabled" name="removetokenicon">
<component :is="removeTokenIcon ? 'span' : 'TimesCircleIcon'" :class="['p-multiselect-token-icon', removeTokenIcon]" @click.stop="removeOption($event, item)" />
</slot>
</div> </div>
<template v-if="!modelValue || modelValue.length === 0">{{ placeholder || 'empty' }}</template> <template v-if="!modelValue || modelValue.length === 0">{{ placeholder || 'empty' }}</template>
</template> </template>
@ -42,7 +44,8 @@
</div> </div>
<div class="p-multiselect-trigger"> <div class="p-multiselect-trigger">
<slot name="indicator"> <slot name="indicator">
<span :class="dropdownIconClass" aria-hidden="true"></span> <component v-if="loading" :is="loadingIcon ? 'span' : 'SpinnerIcon'" spin :class="['p-multiselect-trigger-icon', loadingIcon]" aria-hidden="true" />
<component v-else :is="dropdownIcon ? 'span' : 'ChevronDownIcon'" :class="['p-multiselect-trigger-icon', dropdownIcon]" aria-hidden="true" />
</slot> </slot>
</div> </div>
<Portal :appendTo="appendTo"> <Portal :appendTo="appendTo">
@ -56,7 +59,9 @@
<input type="checkbox" readonly :checked="allSelected" :aria-label="toggleAllAriaLabel" @focus="onHeaderCheckboxFocus" @blur="onHeaderCheckboxBlur" /> <input type="checkbox" readonly :checked="allSelected" :aria-label="toggleAllAriaLabel" @focus="onHeaderCheckboxFocus" @blur="onHeaderCheckboxBlur" />
</div> </div>
<div :class="['p-checkbox-box', { 'p-highlight': allSelected, 'p-focus': headerCheckboxFocused }]"> <div :class="['p-checkbox-box', { 'p-highlight': allSelected, 'p-focus': headerCheckboxFocused }]">
<span :class="['p-checkbox-icon', { [checkboxIcon]: allSelected }]"></span> <slot name="headercheckboxicon" :allSelected="allSelected">
<component :is="checkboxIcon ? 'span' : 'CheckIcon'" :class="['p-checkbox-icon', { [checkboxIcon]: allSelected }]" />
</slot>
</div> </div>
</div> </div>
<div v-if="filter" class="p-multiselect-filter-container"> <div v-if="filter" class="p-multiselect-filter-container">
@ -76,13 +81,17 @@
@input="onFilterChange" @input="onFilterChange"
v-bind="filterInputProps" v-bind="filterInputProps"
/> />
<span :class="['p-multiselect-filter-icon', filterIcon]" /> <slot name="filtericon">
<component :is="filterIcon ? 'span' : 'SearchIcon'" :class="['p-multiselect-filter-icon', filterIcon]" />
</slot>
</div> </div>
<span v-if="filter" role="status" aria-live="polite" class="p-hidden-accessible"> <span v-if="filter" role="status" aria-live="polite" class="p-hidden-accessible">
{{ filterResultMessageText }} {{ filterResultMessageText }}
</span> </span>
<button v-ripple class="p-multiselect-close p-link" :aria-label="closeAriaLabel" @click="onCloseClick" type="button" v-bind="closeButtonProps"> <button v-ripple class="p-multiselect-close p-link" :aria-label="closeAriaLabel" @click="onCloseClick" type="button" v-bind="closeButtonProps">
<span :class="['p-multiselect-close-icon', closeIcon]" /> <slot name="closeicon">
<component :is="closeIcon ? 'span' : 'TimesIcon'" :class="['p-multiselect-close-icon', closeIcon]" />
</slot>
</button> </button>
</div> </div>
<div class="p-multiselect-items-wrapper" :style="{ 'max-height': virtualScrollerDisabled ? scrollHeight : '' }"> <div class="p-multiselect-items-wrapper" :style="{ 'max-height': virtualScrollerDisabled ? scrollHeight : '' }">
@ -110,7 +119,9 @@
> >
<div class="p-checkbox p-component"> <div class="p-checkbox p-component">
<div :class="['p-checkbox-box', { 'p-highlight': isSelected(option) }]"> <div :class="['p-checkbox-box', { 'p-highlight': isSelected(option) }]">
<span :class="['p-checkbox-icon', { [checkboxIcon]: isSelected(option) }]"></span> <slot name="itemcheckboxicon" :selected="isSelected(option)">
<component :is="checkboxIcon ? 'span' : 'CheckIcon'" :class="['p-checkbox-icon', { [checkboxIcon]: isSelected(option) }]" />
</slot>
</div> </div>
</div> </div>
<slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)"> <slot name="option" :option="option" :index="getOptionIndex(i, getItemOptions)">
@ -147,6 +158,12 @@
<script> <script>
import { FilterService } from 'primevue/api'; import { FilterService } from 'primevue/api';
import CheckIcon from 'primevue/icon/check';
import ChevronDownIcon from 'primevue/icon/chevrondown';
import SearchIcon from 'primevue/icon/search';
import SpinnerIcon from 'primevue/icon/spinner';
import TimesIcon from 'primevue/icon/times';
import TimesCircleIcon from 'primevue/icon/timescircle';
import OverlayEventBus from 'primevue/overlayeventbus'; import OverlayEventBus from 'primevue/overlayeventbus';
import Portal from 'primevue/portal'; import Portal from 'primevue/portal';
import Ripple from 'primevue/ripple'; import Ripple from 'primevue/ripple';
@ -240,27 +257,27 @@ export default {
}, },
checkboxIcon: { checkboxIcon: {
type: String, type: String,
default: 'pi pi-check' default: undefined
}, },
closeIcon: { closeIcon: {
type: String, type: String,
default: 'pi pi-times' default: undefined
}, },
dropdownIcon: { dropdownIcon: {
type: String, type: String,
default: 'pi pi-chevron-down' default: undefined
}, },
filterIcon: { filterIcon: {
type: String, type: String,
default: 'pi pi-search' default: undefined
}, },
loadingIcon: { loadingIcon: {
type: String, type: String,
default: 'pi pi-spinner pi-spin' default: undefined
}, },
removeTokenIcon: { removeTokenIcon: {
type: String, type: String,
default: 'pi pi-times-circle' default: undefined
}, },
selectAll: { selectAll: {
type: Boolean, type: Boolean,
@ -1060,9 +1077,6 @@ export default {
} }
]; ];
}, },
dropdownIconClass() {
return ['p-multiselect-trigger-icon', this.loading ? this.loadingIcon : this.dropdownIcon];
},
panelStyleClass() { panelStyleClass() {
return [ return [
'p-multiselect-panel p-component', 'p-multiselect-panel p-component',
@ -1191,7 +1205,13 @@ export default {
}, },
components: { components: {
VirtualScroller: VirtualScroller, VirtualScroller: VirtualScroller,
Portal: Portal Portal: Portal,
TimesIcon: TimesIcon,
SearchIcon: SearchIcon,
TimesCircleIcon: TimesCircleIcon,
ChevronDownIcon: ChevronDownIcon,
SpinnerIcon: SpinnerIcon,
CheckIcon: CheckIcon
} }
}; };
</script> </script>