DigitalConsumer.FixMyGlass/src/common-components/textbox-question/textbox-question.vue
2022-05-16 17:31:25 -04:00

185 lines
3.9 KiB
Vue

<template>
<div class="textbox-question" :class="(errors && errors.length) || hasError ? 'has-error' : ''">
<label :for="inputId" :aria-label="questionText" class="form-label" v-html="labelText"></label>
<!-- See https://stackoverflow.com/a/30976223 for information about "do-not-autofill" -->
<input
v-model="value"
v-maska="mask"
:type="type"
class="form-control"
:ref="inputId"
:id="inputId"
:name="inputId"
:placeholder="placeholderText"
:aria-disabled="isDisabled"
:disabled="isDisabled"
:aria-required="isRequired"
autocomplete="do-not-autofill"
:class="[hasIcon ? 'has-icon' : '', iconRight ? 'icon-right' : '']"
:validationRules="validationRules"
/>
<div v-show="errorMessage" class="row my-2 form-test-error">
<span role="alert">{{ errorMessage }}</span>
</div>
</div>
</template>
<script>
import { useField } from "vee-validate";
export default {
name: "textbox-question",
props: {
type: {
type: String,
default: 'text',
},
placeholderText: {
type: String,
default: '',
},
modelValue: String,
inputId: String,
isDisabled: Boolean,
isRequired: Boolean,
disableAutoFill: Boolean,
hasIcon: Boolean, // If input has an icon
iconRight: Boolean, // Place icon on right side of text input, otherwise default is left if hasIcon prop is used
hasError: Boolean,
mask: {
type: String,
default: '',
},
validationRules: String,
cmsWidgetName: String
},
setup(props) {
const propsClone = Object.assign({}, props);
const modelValue = propsClone.modelValue;
let initialValue;
switch (typeof modelValue) {
case "number":
initialValue = modelValue;
break;
default:
initialValue = (modelValue && modelValue.length > 0) ? modelValue : "";
break;
}
const fieldOptions = {
type: "text",
value: modelValue,
initialValue: initialValue
};
const {
errorMessage,
handleBlur,
handleChange,
meta,
validate,
errors,
} = useField(props.inputId, props.validationRules, fieldOptions);
return {
errorMessage,
handleBlur,
handleChange,
validate,
meta,
errors,
};
},
computed: {
questionText(){
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
},
value: {
get: function() {
return this.modelValue;
},
set: function(newValue) {
this.$emit("update:modelValue", newValue);
}
},
labelText: {
get: function () {
const noBreakChar = "&NoBreak;";
var questionText = "";
if (this.disableAutoFill) {
var words = this.questionText.toString().split(/[ ]+/);
words.forEach(function (word) {
const position = 1;
word = [word.toString().slice(0, position), noBreakChar, word.toString().slice(position)].join('');
questionText += `${word} `;
});
questionText = questionText.trimEnd();
} else {
questionText = this.questionText.toString();
}
return questionText;
}
}
},
watch: {
value(newValue) {
this.handleChange(newValue);
}
}
};
</script>
<style lang="scss">
.textbox-question {
label {
color: $black;
font-weight: 500;
}
input {
&.has-icon {
background-image: url(~@/assets/img/icons/location-pin.svg);
background-repeat: no-repeat;
background-position: .75rem 50%;
background-size: 1rem auto;
padding: 0 0.75rem 0 2.5rem;
&.icon-right {
background-position: calc(100% - .75rem) 50%;
padding: 0 2.5rem 0 0.75rem
}
}
}
.form-label {
margin-bottom: .25rem;
}
.form-control {
border: 1px solid $gray-500;
border-radius: .5rem;
min-height: 3rem;
&::placeholder {
color: $gray-500;
}
&:focus {
box-shadow: 0 0 0 2.5px $blue;
}
&:disabled,
&.disabled {
background-color: $gray-100;
&:hover {
box-shadow: 0 0 0 4px transparent;
border: 1px solid $gray-500;
}
}
&:hover {
border: 1px solid $gray-500;
box-shadow: 0 0 0 4px $blue-300;
}
}
p {
display: none;
}
}
</style>