Open mahfuz01-2023 opened 6 months ago
I am using yup to validate a form in vue3 using vee-validate
Bellow is my code. All validations are working as expected except file. Not sure how to approach it, any help is much appreciated.
<script setup lang="ts"> interface FormModel { name?: string | null; email?: string | null; phone?: string | null; address?: string | null; resume?: File | null; } import { ref } from 'vue'; import { useForm } from 'vee-validate'; import { mixed, object, string } from 'yup'; import { toTypedSchema } from '@vee-validate/yup'; // vle form element components import VleTextField from '@/components/Core/formElements/VleTextField.vue'; import VleFileInput from '@/components/Core/formElements/VleFileInput.vue'; const customEmailErrorMessage = ref(''); const customEmailValidationInProgress = ref(false); const supportedFileFormats = ref([ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/pdf' ]); const maxFileSize = ref(20 * 1024 * 1024); const { errors, handleSubmit, handleReset, defineField } = useForm<FormModel>({ validationSchema: toTypedSchema(object( { name: string() .required('Name is required'), email: string() .email('Invalid email format') .required('Email is required') .test('customError', (currentValue, context) => { return currentValue && currentValue.startsWith('_') ? context.createError({ message: `${customEmailErrorMessage.value}`, path: 'email' }) : true; }), phone: string() .matches(/^(?:\+?61|0)4(?:[ -]?\d){8}$/, 'Phone must be in Aus mobile format') .required('Phone is required'), address: string() .optional(), resume: mixed() .nullable() .required('Resume is required') .test('fileSize', 'Maximum file size allowed is 20MB', (file) => { return !file || (file && file.size <= maxFileSize.value); }) .test('fileType', 'Allowed file types are .docx, .pdf', (file) => { return !file || (file && supportedFileFormats.value.includes(file.type)); }), })) }); const formBtnLoading = ref(false); const [name, nameAttrs] = defineField('name'); const [email, emailAttrs] = defineField('email'); const [phone, phoneAttrs] = defineField('phone'); const [address, addressAttrs] = defineField('address'); const [resume, resumeAttrs] = defineField('resume'); const onSubmit = handleSubmit(values => { formBtnLoading.value = true; console.log('Vee-validate new form > submit clicked'); console.log(`Name: ${values.name}`); console.log(`Email: ${values.email}`); console.log(`Phone: ${values.phone}`); console.log(`Address: ${values.address}`); }) const onReset = () => { formBtnLoading.value = false; console.log('Vee-validate new form > reset clicked') handleReset(); } function verifyEmail() { customEmailValidationInProgress.value = true; setTimeout(() => { new Promise<boolean>((resolve, reject) => { const serverError = true; customEmailErrorMessage.value = `This is custom error # ${new Date().getTime()}`; resolve(serverError); }).then((hasError) => { email.value = hasError && !email.value?.startsWith('_') ? `_${email.value}` : email.value; customEmailValidationInProgress.value = false; }); }, 2000); } </script> <template> <v-expansion-panel class="vee-validate-form-panel"> <template #title> <h4>Examples</h4> </template> <template #text> <form class="pt-5"> <v-row> <v-col sm="12" lg="6" > <vle-text-field v-model="name" v-bind="nameAttrs" required :error-messages="errors.name" label="Name" /> </v-col> <v-col sm="12" lg="6" > <vle-text-field v-model="email" v-bind="emailAttrs" :error-messages="errors.email" required label="Email" type="email" > <template #append-inner> <ads-progress-circular v-if="customEmailValidationInProgress" indeterminate size="30" /> <ads-icon v-else size="large" icon="mdi-magnify" @click="verifyEmail" /> </template> </vle-text-field> </v-col> <v-col sm="12" lg="6" > <vle-text-field v-model="phone" v-bind="phoneAttrs" :error-messages="errors.phone" required label="Phone" /> </v-col> <v-col sm="12" lg="6" > <vle-text-field v-model="address" v-bind="addressAttrs" :error-messages="errors.address" label="Address" /> </v-col> <v-col sm="12" lg="6" > <vle-file-input v-model="resume" v-bind="resumeAttrs" :error-messages="errors.resume" prepend-icon="" prepend-inner-icon="mdi-paperclip" required hint=".docx or .pdf file allowed with maximum size of 20MB" label="Resume" /> </v-col> </v-row> <v-row> <v-spacer /> <ads-btn prepend-icon="mdi-check" color="primary-1" :loading="formBtnLoading" @click="onSubmit" > Submit </ads-btn> <ads-btn color="primary-1" prepend-icon="mdi-reload" @click="onReset" > Reset </ads-btn> </v-row> </form> </template> </v-expansion-panel> </template>
I am using yup to validate a form in vue3 using vee-validate
Bellow is my code. All validations are working as expected except file. Not sure how to approach it, any help is much appreciated.