133 lines
3.8 KiB
Vue
133 lines
3.8 KiB
Vue
<template>
|
|
<div class="phonenumber-question d-flex flex-column">
|
|
<label for="phone-number" class="mb-1 fw-bold" v-html="phoneNumberQuestionWidget"></label>
|
|
<input
|
|
class="form-control"
|
|
id="phone-number"
|
|
v-model="phoneNumber"
|
|
@input="formatPhoneNumber"
|
|
:maxlength="phoneNumberMaxLength"
|
|
pattern="[0-9\-]+"
|
|
:aria-required="isRequired"
|
|
:validationRules="validationRules" />
|
|
<div v-show="errorMessage" class="row my-1 form-test-error">
|
|
<span
|
|
class="d-inline-flex small mt-0"
|
|
role="alert"
|
|
:class="[centerErrorMessage ? 'center-error-message' : '']"
|
|
>{{ errorMessage }}</span
|
|
>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { useField, validate } from "vee-validate";
|
|
export default {
|
|
name: "phoneNumberQuestion",
|
|
props: {
|
|
cmsWidgetName: String,
|
|
isRequired: Boolean,
|
|
validationRules: String,
|
|
hasError: Boolean,
|
|
centerErrorMessage: Boolean,
|
|
},
|
|
setup(props) {
|
|
const inputId = !props.customInputId ? `input-${crypto.randomUUID()}` : props.customInputId;
|
|
|
|
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(
|
|
inputId,
|
|
props.validationRules,
|
|
fieldOptions
|
|
);
|
|
|
|
return {
|
|
inputId,
|
|
errorMessage,
|
|
handleBlur,
|
|
handleChange,
|
|
validate,
|
|
meta,
|
|
errors,
|
|
};
|
|
},
|
|
data() {
|
|
return {
|
|
phoneNumber: "",
|
|
phoneNumberMaxLength: 12,
|
|
};
|
|
},
|
|
computed: {
|
|
phoneNumberQuestionWidget() {
|
|
return this.getCmsContent(this.cmsWidgetName, "QuestionText");
|
|
},
|
|
},
|
|
methods: {
|
|
formatPhoneNumber() {
|
|
// Remove all non-digit characters from the phone number
|
|
let formattedNumber = this.phoneNumber.replace(/\D/g, "");
|
|
|
|
// Insert hyphens after the first three and the next three digits
|
|
if (formattedNumber.length > 3) {
|
|
formattedNumber = formattedNumber.slice(0, 3) + "-" + formattedNumber.slice(3);
|
|
}
|
|
if (formattedNumber.length > 7) {
|
|
formattedNumber = formattedNumber.slice(0, 7) + "-" + formattedNumber.slice(7);
|
|
}
|
|
|
|
// Update the phone number with the formatted version
|
|
this.phoneNumber = formattedNumber;
|
|
},
|
|
},
|
|
mounted() {
|
|
this.$nextTick(() => {
|
|
// Prevent "1" as the first number
|
|
const inputElement = document.getElementById("phone-number");
|
|
inputElement.addEventListener("keydown", (event) => {
|
|
if (inputElement.selectionStart === 0 && event.key === "1") {
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
});
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.phonenumber-question {
|
|
label {
|
|
color: $black;
|
|
}
|
|
input {
|
|
border-radius: 0.5rem;
|
|
border: 1px solid $gray-500;
|
|
height: 48px;
|
|
&:focus {
|
|
box-shadow: 0 0 0 2.5px $blue;
|
|
outline: none;
|
|
}
|
|
&:hover {
|
|
box-shadow: 0 0 0 4px $blue-300;
|
|
}
|
|
}
|
|
}
|
|
</style>
|