Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can't set the rules to validate file size and extension #2204

Open
mahfuz01-2023 opened this issue Apr 22, 2024 · 0 comments
Open

can't set the rules to validate file size and extension #2204

mahfuz01-2023 opened this issue Apr 22, 2024 · 0 comments

Comments

@mahfuz01-2023
Copy link

mahfuz01-2023 commented Apr 22, 2024

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>
          &nbsp;&nbsp;
          <ads-btn
            color="primary-1"
            prepend-icon="mdi-reload"
            @click="onReset"
          >
            Reset
          </ads-btn>
        </v-row>
      </form>
    </template>            
  </v-expansion-panel>
</template>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant