Add form support to `CascadeSelect`

pull/6632/head
Mert Sincan 2024-10-18 16:29:18 +01:00
parent 61208c4d46
commit a7a1cc35f4
3 changed files with 22 additions and 40 deletions

View File

@ -1,12 +1,11 @@
<script> <script>
import BaseComponent from '@primevue/core/basecomponent'; import BaseInput from '@primevue/core/baseinput';
import CascadeSelectStyle from 'primevue/cascadeselect/style'; import CascadeSelectStyle from 'primevue/cascadeselect/style';
export default { export default {
name: 'BaseCascadeSelect', name: 'BaseCascadeSelect',
extends: BaseComponent, extends: BaseInput,
props: { props: {
modelValue: null,
options: Array, options: Array,
optionLabel: null, optionLabel: null,
optionValue: null, optionValue: null,
@ -18,15 +17,6 @@ export default {
type: String, type: String,
default: '960px' default: '960px'
}, },
variant: {
type: String,
default: null
},
invalid: {
type: Boolean,
default: false
},
disabled: Boolean,
dataKey: null, dataKey: null,
inputId: { inputId: {
type: String, type: String,
@ -135,10 +125,6 @@ export default {
ariaLabel: { ariaLabel: {
type: String, type: String,
default: null default: null
},
fluid: {
type: Boolean,
default: null
} }
}, },
style: CascadeSelectStyle, style: CascadeSelectStyle,

View File

@ -26,7 +26,7 @@
/> />
</div> </div>
<span :class="cx('label')" v-bind="ptm('label')"> <span :class="cx('label')" v-bind="ptm('label')">
<slot name="value" :value="modelValue" :placeholder="placeholder"> <slot name="value" :value="d_value" :placeholder="placeholder">
{{ label }} {{ label }}
</slot> </slot>
</span> </span>
@ -53,7 +53,7 @@
@keydown="onOverlayKeyDown" @keydown="onOverlayKeyDown"
v-bind="{ ...panelProps, ...overlayProps, ...ptm('overlay') }" v-bind="{ ...panelProps, ...overlayProps, ...ptm('overlay') }"
> >
<slot name="header" :value="modelValue" :options="options" /> <slot name="header" :value="d_value" :options="options" />
<div :class="cx('listContainer')" v-bind="ptm('listContainer')"> <div :class="cx('listContainer')" v-bind="ptm('listContainer')">
<CascadeSelectSub <CascadeSelectSub
:id="id + '_tree'" :id="id + '_tree'"
@ -71,7 +71,7 @@
:optionGroupIcon="optionGroupIcon" :optionGroupIcon="optionGroupIcon"
:optionGroupLabel="optionGroupLabel" :optionGroupLabel="optionGroupLabel"
:optionGroupChildren="optionGroupChildren" :optionGroupChildren="optionGroupChildren"
:value="modelValue" :value="d_value"
@option-change="onOptionClick" @option-change="onOptionClick"
@option-focus-change="onOptionMouseMove" @option-focus-change="onOptionMouseMove"
@option-focus-enter-change="onOptionMouseEnter" @option-focus-enter-change="onOptionMouseEnter"
@ -82,7 +82,7 @@
<span role="status" aria-live="polite" class="p-hidden-accessible" v-bind="ptm('hiddenSelectedMessage')" :data-p-hidden-accessible="true"> <span role="status" aria-live="polite" class="p-hidden-accessible" v-bind="ptm('hiddenSelectedMessage')" :data-p-hidden-accessible="true">
{{ selectedMessageText }} {{ selectedMessageText }}
</span> </span>
<slot name="footer" :value="modelValue" :options="options" /> <slot name="footer" :value="d_value" :options="options" />
</div> </div>
</transition> </transition>
</Portal> </Portal>
@ -106,10 +106,7 @@ export default {
name: 'CascadeSelect', name: 'CascadeSelect',
extends: BaseCascadeSelect, extends: BaseCascadeSelect,
inheritAttrs: false, inheritAttrs: false,
emits: ['update:modelValue', 'change', 'focus', 'blur', 'click', 'group-change', 'before-show', 'before-hide', 'hide', 'show'], emits: ['change', 'focus', 'blur', 'click', 'group-change', 'before-show', 'before-hide', 'hide', 'show'],
inject: {
$pcFluid: { default: null }
},
outsideClickListener: null, outsideClickListener: null,
matchMediaListener: null, matchMediaListener: null,
scrollHandler: null, scrollHandler: null,
@ -193,9 +190,9 @@ export default {
show(isFocus) { show(isFocus) {
this.$emit('before-show'); this.$emit('before-show');
this.overlayVisible = true; this.overlayVisible = true;
this.activeOptionPath = this.hasSelectedOption ? this.findOptionPathByValue(this.modelValue) : this.activeOptionPath; this.activeOptionPath = this.$filled ? this.findOptionPathByValue(this.d_value) : this.activeOptionPath;
if (this.hasSelectedOption && isNotEmpty(this.activeOptionPath)) { if (this.$filled && isNotEmpty(this.activeOptionPath)) {
const processedOption = this.activeOptionPath[this.activeOptionPath.length - 1]; const processedOption = this.activeOptionPath[this.activeOptionPath.length - 1];
this.focusedOptionInfo = { index: processedOption.index, level: processedOption.level, parentKey: processedOption.parentKey }; this.focusedOptionInfo = { index: processedOption.index, level: processedOption.level, parentKey: processedOption.parentKey };
@ -234,6 +231,7 @@ export default {
this.focusedOptionInfo = { index: -1, level: 0, parentKey: '' }; this.focusedOptionInfo = { index: -1, level: 0, parentKey: '' };
this.searchValue = ''; this.searchValue = '';
this.$emit('blur', event); this.$emit('blur', event);
this.formField.onBlur?.();
}, },
onKeyDown(event) { onKeyDown(event) {
if (this.disabled || this.loading) { if (this.disabled || this.loading) {
@ -357,7 +355,7 @@ export default {
}, },
onOptionMouseEnter(event) { onOptionMouseEnter(event) {
if (this.focusOnHover) { if (this.focusOnHover) {
if (this.dirty || (!this.dirty && isNotEmpty(this.modelValue))) { if (this.dirty || (!this.dirty && isNotEmpty(this.d_value))) {
this.onOptionChange({ ...event, type: 'hover' }); this.onOptionChange({ ...event, type: 'hover' });
} else if (!this.dirty && event.processedOption.level === 0) { } else if (!this.dirty && event.processedOption.level === 0) {
this.onOptionClick({ ...event, type: 'hover' }); this.onOptionClick({ ...event, type: 'hover' });
@ -756,7 +754,7 @@ export default {
}); });
}, },
autoUpdateModel() { autoUpdateModel() {
if (this.selectOnFocus && this.autoOptionFocus && !this.hasSelectedOption) { if (this.selectOnFocus && this.autoOptionFocus && !this.$filled) {
this.focusedOptionInfo.index = this.findFirstFocusedOptionIndex(); this.focusedOptionInfo.index = this.findFirstFocusedOptionIndex();
this.onOptionChange({ processedOption: this.visibleOptions[this.focusedOptionInfo.index], isHide: false }); this.onOptionChange({ processedOption: this.visibleOptions[this.focusedOptionInfo.index], isHide: false });
@ -764,7 +762,7 @@ export default {
} }
}, },
updateModel(event, value) { updateModel(event, value) {
this.$emit('update:modelValue', value); this.updateValue(value, event);
this.$emit('change', { originalEvent: event, value }); this.$emit('change', { originalEvent: event, value });
}, },
createProcessedOptions(options, level = 0, parent = {}, parentKey = '') { createProcessedOptions(options, level = 0, parent = {}, parentKey = '') {
@ -793,14 +791,15 @@ export default {
} }
}, },
computed: { computed: {
// @deprecated use $filled instead.
hasSelectedOption() { hasSelectedOption() {
return isNotEmpty(this.modelValue); return this.$filled;
}, },
label() { label() {
const label = this.placeholder || 'p-emptylabel'; const label = this.placeholder || 'p-emptylabel';
if (this.hasSelectedOption) { if (this.$filled) {
const activeOptionPath = this.findOptionPathByValue(this.modelValue); const activeOptionPath = this.findOptionPathByValue(this.d_value);
const processedOption = isNotEmpty(activeOptionPath) ? activeOptionPath[activeOptionPath.length - 1] : null; const processedOption = isNotEmpty(activeOptionPath) ? activeOptionPath[activeOptionPath.length - 1] : null;
return processedOption ? this.getOptionLabel(processedOption.option) : label; return processedOption ? this.getOptionLabel(processedOption.option) : label;
@ -838,13 +837,10 @@ export default {
return this.emptySelectionMessage || this.$primevue.config.locale.emptySelectionMessage || ''; return this.emptySelectionMessage || this.$primevue.config.locale.emptySelectionMessage || '';
}, },
selectedMessageText() { selectedMessageText() {
return this.hasSelectedOption ? this.selectionMessageText.replaceAll('{0}', '1') : this.emptySelectionMessageText; return this.$filled ? this.selectionMessageText.replaceAll('{0}', '1') : this.emptySelectionMessageText;
}, },
focusedOptionId() { focusedOptionId() {
return this.focusedOptionInfo.index !== -1 ? `${this.id}${isNotEmpty(this.focusedOptionInfo.parentKey) ? '_' + this.focusedOptionInfo.parentKey : ''}_${this.focusedOptionInfo.index}` : null; return this.focusedOptionInfo.index !== -1 ? `${this.id}${isNotEmpty(this.focusedOptionInfo.parentKey) ? '_' + this.focusedOptionInfo.parentKey : ''}_${this.focusedOptionInfo.index}` : null;
},
hasFluid() {
return isEmpty(this.fluid) ? !!this.$pcFluid : this.fluid;
} }
}, },
components: { components: {

View File

@ -220,13 +220,13 @@ const classes = {
{ {
'p-cascadeselect-mobile': instance.queryMatches, 'p-cascadeselect-mobile': instance.queryMatches,
'p-disabled': props.disabled, 'p-disabled': props.disabled,
'p-invalid': props.invalid, 'p-invalid': instance.$invalid,
'p-variant-filled': props.variant ? props.variant === 'filled' : instance.$primevue.config.inputStyle === 'filled' || instance.$primevue.config.inputVariant === 'filled', 'p-variant-filled': instance.$variant === 'filled',
'p-focus': instance.focused, 'p-focus': instance.focused,
'p-inputwrapper-filled': props.modelValue, 'p-inputwrapper-filled': instance.$filled,
'p-inputwrapper-focus': instance.focused || instance.overlayVisible, 'p-inputwrapper-focus': instance.focused || instance.overlayVisible,
'p-cascadeselect-open': instance.overlayVisible, 'p-cascadeselect-open': instance.overlayVisible,
'p-cascadeselect-fluid': instance.hasFluid 'p-cascadeselect-fluid': instance.$fluid
} }
], ],
label: ({ instance, props }) => [ label: ({ instance, props }) => [