DigitalConsumer.ISS/src/digital-components/dropdown-question/dropdown-question.vue

189 lines
5 KiB
Vue

<template>
<div
class="dropdown-question"
:class="{
'has-error' : (meta?.touched && errors && errors.length && !isDisabled) || hasError,
'has-success': (meta?.touched && (!errors || !errors.length) && !isDisabled),
[`dropdown-${variant}`]: true
}">
<label
:for="inputId"
:aria-label="questionText"
class="form-label"
v-html="questionText"></label>
<select
:id="inputId"
v-model="selectedOption"
class="form-select"
:name="inputId"
:aria-disabled="isDisabled"
:disabled="isDisabled"
:aria-required="isRequired"
:validationRules="validationRules"
:placeHolderText="placeHolderText">
<option
v-if="placeHolderText"
value=""
selected>
{{ placeHolderText }}
</option>
<option
v-for="(value, name, index) in options"
:key="index"
:value="name">
{{ value }}
</option>
</select>
<div
v-show="meta?.touched && errorMessage && !isDisabled"
class="row mt-1 form-test-error">
<span role="alert">{{ errorMessage }}</span>
</div>
</div>
</template>
<script>
import { dropdownVariants } from '@/constants/component-variants';
import { useField } from 'vee-validate';
export default {
name: 'dropdown-question',
props: {
modelValue: String,
inputId: String,
options: {
type: Object,
required: true
},
isDisabled: Boolean,
isRequired: Boolean,
disableAutoFill: Boolean,
validationRules: String,
cmsWidgetName: String,
hasError: Boolean,
placeHolderText: String,
variant: {
type: String,
default: dropdownVariants.primary
}
},
emits: ['update:modelValue'],
setup(props) {
const propsClone = { ...props };
const { modelValue } = propsClone;
let initialValue;
switch (typeof modelValue) {
case 'number':
initialValue = modelValue;
break;
default:
initialValue = modelValue && modelValue.length > 0 ? modelValue : '';
break;
}
const fieldOptions = {
type: 'select',
value: props.modelValue,
initialValue
};
const { errorMessage,
handleBlur,
handleChange,
setTouched,
meta, errors,
setErrors } = useField(props.inputId, props.validationRules, fieldOptions);
return {
errorMessage,
handleBlur,
handleChange,
meta,
errors,
setTouched,
setErrors
};
},
computed: {
questionText() {
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
},
selectedOption: {
get() {
return !this.modelValue ? '' : this.modelValue;
},
set(newValue) {
this.$emit('update:modelValue', newValue);
}
}
},
watch: {
isDisabled(newValue, oldValue) {
if (newValue !== oldValue) {
this.setTouched(false, null);
}
},
selectedOption(newValue) {
this.handleChange(newValue);
}
}
};
</script>
<style lang="scss" scoped>
.dropdown-question {
label {
color: $black;
font-weight: 600;
}
.form-label {
margin-bottom: 0.25rem;
}
.form-select {
border: $border-input;
background-image: url(~@/assets/img/icons/select.png);
background-size: 0.625rem 1rem;
color: $gray-600;
border-radius: $border-radius;
min-height: 2.8125rem;
letter-spacing: inherit;
box-shadow: $box-shadow-input;
&:focus,
&:focus-visible {
border: $border-input-focus;
}
&:disabled,
&.disabled {
background-color: $gray-100;
color: $gray-500;
filter: grayscale(100%);
}
}
&.dropdown-compact {
display: flex;
align-items: center;
justify-content: flex-end;
margin-bottom: 1.25rem;
.form-label {
color: $darker-gray;
font-weight: $font-weight-light;
margin: 0;
}
.form-select {
color: $heritage-blue-secondary;
background-position-x: 98%;
padding: 0;
padding-left: .3125rem;
width: 5.625rem;
min-height: auto;
border: none;
box-shadow: none;
&:focus,
&:focus-visible {
border: .125rem solid $black;
}
}
}
}
</style>