162 lines
3.2 KiB
Vue
162 lines
3.2 KiB
Vue
<template>
|
|
<div class="textbox-question" :class="hasError ? 'has-error' : ''">
|
|
<label :for="inputId" :aria-label="ariaLabelText" class="form-label" v-html="labelText"></label>
|
|
<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="off"
|
|
:class="[hasIcon ? 'has-icon' : '', iconRight ? 'icon-right' : '']"
|
|
:validationRules="validationRules"
|
|
@input="handleChange"
|
|
@blur="handleBlur" />
|
|
<div v-show="errorMessage" class="row mt-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,
|
|
},
|
|
setup(props) {
|
|
const fieldOptions = {
|
|
type: "text",
|
|
value: props.modelValue,
|
|
};
|
|
|
|
const {
|
|
errorMessage,
|
|
handleBlur,
|
|
handleChange,
|
|
meta,
|
|
validate
|
|
} = useField(props.inputId, props.validationRules, fieldOptions);
|
|
|
|
return {
|
|
errorMessage,
|
|
handleBlur,
|
|
handleChange,
|
|
validate,
|
|
meta,
|
|
};
|
|
},
|
|
data() {
|
|
return {
|
|
labelText: "",
|
|
ariaLabelText: "",
|
|
}
|
|
},
|
|
methods: {
|
|
initializeComponent(cmsContent){
|
|
var labelText = cmsContent;
|
|
if (this.disableAutoFill) {
|
|
var noBreakChar = "⁠";
|
|
var position = 1;
|
|
labelText = [labelText.slice(0, position), noBreakChar, labelText.slice(position)].join('');
|
|
}
|
|
|
|
this.labelText = labelText;
|
|
this.ariaLabelText = cmsContent;
|
|
},
|
|
},
|
|
computed: {
|
|
value: {
|
|
get: function() {
|
|
return this.modelValue;
|
|
},
|
|
set: function(newValue) {
|
|
this.$emit("update:modelValue", newValue);
|
|
}
|
|
},
|
|
},
|
|
watch: {
|
|
value(newValue) {
|
|
this.handleChange(newValue);
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.textbox-question {
|
|
label {
|
|
color: $black;
|
|
}
|
|
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>
|