- common-error-styles.scss renamed to common-validation-styles.scss - Added 'has-success' to dropdown-question component - Updated dropdown-question to only show error/success when not disabled - Fixed issue with focusing first invalid input in base-form-mixin
158 lines
4.1 KiB
Vue
158 lines
4.1 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)
|
|
}">
|
|
<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 { 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
|
|
},
|
|
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: 3rem;
|
|
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%);
|
|
}
|
|
}
|
|
}
|
|
</style>
|