Skip to content

Commit

Permalink
improvements to select field
Browse files Browse the repository at this point in the history
  • Loading branch information
darrylhein committed Nov 29, 2024
1 parent 8e96417 commit e0ee521
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 33 deletions.
82 changes: 49 additions & 33 deletions public/js/src/common/field_select.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="field-wrap">
<div v-if="!selectOnly" class="field-wrap">
<slot :id="id" name="label">
<label :for="id" :class="labelClasses"><slot></slot></label>
</slot>
Expand All @@ -8,26 +8,48 @@
<template #required><slot name="required"></slot></template>
</FieldError>

<select :id="id" v-model="value" v-focus="autofocus" :disabled="disabled">
<option :value="null" :disabled="selectOneDisabled">
<slot name="default-option">– Select one –</slot>
</option>
<option v-for="_value in valuesCollection"
:key="_value.value"
:value="_value.value">{{ _value.label }}</option>
</select>
<FieldSelectElement :id="id"
ref="select"
v-model="value"
:values="values"
:autofocus="autofocus"
:disabled="disabled"
:inert="inert"
:required="required"
:select-one-disabled="selectOneDisabled"
:select-classes="selectClasses">
<template #default-option><slot name="default-option"></slot></template>
</FieldSelectElement>

<div v-if="!!$slots.help" class="field-help"><slot name="help"></slot></div>
</div>

<FieldSelectElement v-else
:id="id"
ref="select"
v-model="value"
:values="values"
:autofocus="autofocus"
:disabled="disabled"
:inert="inert"
:required="required"
:select-one-disabled="selectOneDisabled"
:select-classes="selectClasses">
<template #default-option><slot name="default-option"></slot></template>
</FieldSelectElement>
</template>

<script setup>
import { useTemplateRef } from 'vue';
import cuid from 'cuid';
import { computed } from 'vue';
import FieldSelectElement from './field_select_element.vue';
const value = defineModel({ type: [ String, Number ] });
defineExpose({
field: useTemplateRef('select'),
});
const props = defineProps({
defineProps({
/**
* Either:
* [{ value: '', label: '' }, ...]
Expand All @@ -45,14 +67,30 @@ const props = defineProps({
type: Boolean,
default: false,
},
selectOnly: {
type: Boolean,
default: false,
},
labelClasses: {
type: [ String, Array, Object ],
default: null,
},
selectClasses: {
type: [ String, Array, Object ],
default: null,
},
disabled: {
type: Boolean,
default: false,
},
inert: {
type: Boolean,
default: false,
},
required: {
type: Boolean,
default: false,
},
selectOneDisabled: {
type: Boolean,
default: true,
Expand All @@ -68,26 +106,4 @@ const props = defineProps({
},
},
});
const valuesCollection = computed(() => {
if (Array.isArray(props.values)) {
if (typeof props.values[0] === 'string' || typeof props.values[0] === 'number') {
return props.values.map((value) => {
return {
value,
label: value,
};
});
}
return props.values;
}
return Object.keys(props.values).map((value) => {
return {
value,
label: props.values[value],
};
});
});
</script>
88 changes: 88 additions & 0 deletions public/js/src/common/field_select_element.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<template>
<select :id="id"
ref="select"
v-focus="autofocus"
:disabled="disabled"
:inert="inert"
:required="required"
@change="value = $event.target.value">
<option value="" :selected="null === value" :disabled="selectOneDisabled">
<slot name="default-option">– Select one –</slot>
</option>
<option v-for="_value in valuesCollection"
:key="_value.value"
:value="_value.value"
:selected="_value.value === value">{{ _value.label }}</option>
</select>
</template>

<script setup>
import { computed, useTemplateRef } from 'vue';
const value = defineModel({ type: [ String, Number ] });
defineExpose({
field: useTemplateRef('select'),
});
const props = defineProps({
/**
* Either:
* [{ value: '', label: '' }, ...]
* or
* { value: name, ... }
* or
* [ value, value, ... ]
* The first is used by the component. The second and third are converted to the first.
*/
values: {
type: [Array, Object],
required: true,
},
autofocus: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
inert: {
type: Boolean,
default: false,
},
required: {
type: Boolean,
default: false,
},
selectOneDisabled: {
type: Boolean,
default: true,
},
id: {
type: String,
default: null,
},
});
const valuesCollection = computed(() => {
if (Array.isArray(props.values)) {
if (typeof props.values[0] === 'string' || typeof props.values[0] === 'number') {
return props.values.map((value) => {
return {
value,
label: value,
};
});
}
return props.values;
}
return Object.keys(props.values).map((value) => {
return {
value,
label: props.values[value],
};
});
});
</script>

0 comments on commit e0ee521

Please sign in to comment.