NumberFrmate
unknown
javascript
a year ago
4.2 kB
6
Indexable
<template>
<div class="mb-0 input-form" :class="divClass">
<FormBaseLabel v-if="label" :label="label" :required="required" />
<div class="phone_field">
<input
:id="id"
:name="type"
:type="type"
v-model.trim="telNumber"
@input="numberFormatting"
@focus="focus"
@keydown="keydownHandler"
v-bind="$attrs"
:placeholder="placeholder"
class="form_input"
:class="[errorMessage || error ? 'isWarning' : '', classes]"
:style="{ paddingLeft: type === 'search' ? '40px' : '' }"
:autocomplete="autocomplete"
:disabled="disabled"
:autofocus="autofocus"
:required="required"
:min="min"
:max="maxNumberLength"
ref="inputRef"
/>
</div>
</div>
<transition name="fade-in">
<p class="form_error_message" v-if="error">
<Icon name="ri:error-warning-fill" />
<span>{{ error }}</span>
</p>
</transition>
</template>
<script setup>
const props = defineProps({
modelValue: {
type: [String, Number],
default: 0,
},
type: {
type: String,
default: 'tel', // Possible values: 'text', 'phone'
},
label: {
type: String,
default: '',
},
id: {
type: String,
default: '',
},
name: {
type: String,
default: '',
},
placeholder: {
type: String,
default: '019XXXXXXXX',
},
divClass: {
type: String,
default: '',
},
classes: {
type: String,
default: '',
},
required: {
type: Boolean,
default: false,
},
error: {
type: String,
default: '',
},
autocomplete: {
type: String,
default: 'off',
},
disabled: {
type: Boolean,
default: false,
},
autofocus: {
type: Boolean,
default: false,
},
sanitizeInput: {
type: Boolean,
default: false,
},
min: {
type: Number,
default: null,
},
max: {
type: Number,
default: 11,
},
});
const emit = defineEmits(['update:modelValue']);
const errorMessage = ref('');
const telNumber = ref('');
const maxNumberLength = ref(props.max);
const inputRef = ref(null);
const isError = ref(false);
let value = '';
// formate BD mobile & tel number
const formatPhone = (str) => {
const digits = String(str)?.replace(/\D/g, '');
if (/^02/.test(digits) && digits.length <= 9) {
maxNumberLength.value = 9;
isError.value = false;
return `${digits.slice(0, 2)}-${digits.slice(2)}`;
}
if ((/^01/.test(digits) || /^09/.test(digits)) && digits.length <= 11) {
maxNumberLength.value = 11;
isError.value = false;
return `${digits.slice(0, 5)}-${digits.slice(5)}`;
}
return '';
};
// remove hyphen
const keydownHandler = (e) => {
if (e.key === 'Backspace' && telNumber.value.endsWith('-')) {
e.preventDefault();
telNumber.value = telNumber.value.slice(0, -1);
}
};
const numberFormatting = (e) => {
const formattedNumber = formatPhone(e.target.value);
if (formattedNumber !== '') {
telNumber.value = formattedNumber;
value = formattedNumber;
} else {
e.target.value = telNumber.value;
isError.value = true;
}
// prevent input if exceed maximum length
if (telNumber.value.length >= maxNumberLength.value) {
telNumber.value = value;
e.preventDefault();
}
emit('update:modelValue', telNumber.value?.replace('-', ''));
};
const focus = () => {
telNumber.value = telNumber.value;
};
watch(
() => isError.value,
(newVal, oldVal) => {
if (newVal) {
errorMessage.value = 'Please input a valid number';
} else {
errorMessage.value = '';
}
},
{ deep: true, immediate: true },
);
// set default value
watchEffect(() => {
if (isEmpty(telNumber.value)) {
telNumber.value = formatPhone(props.modelValue);
}
});
const focusInput = () => {
if (inputRef.value && inputRef.value.focus) {
inputRef.value.focus();
}
};
onMounted(() => {
if (props.autofocus) {
focusInput();
}
});
</script>Editor is loading...
Leave a Comment