vue.jsvuetify.jsvee-validate

Veutify v-file-input validation


I would like to validate if a file has been chosen using v-file-input and ValidationProvider from vee-validate.

Below is my code:

<v-flex>
  <ValidationProvider rules="required" v-slot="{ errors }">
    <v-file-input
      show-size
      accept=".xlsx"
      placeholder="Click here to select your file"
      label="File name"
      :error="errors.length > 0"
      :error-messages="errors[0]"
      @change="selectFile"
    >
    </v-file-input>
  </ValidationProvider>
</v-flex>

Somehow the validation works but it works too well even after I have chosen a file:

enter image description here

I am not sure what I have done wrong?


Solution

  • This was due to the fact that the v-file-input component actually returns an array of File objects in vue 3 (i.e., File[]), not a single File even though it's a single file upload and you kept multiple="false". Thus, the validation rules were not being applied correctly. Thats why, the validation was often failing because v was undefined.

    To resolve this, I needed to update the validation rules to accept an array of File objects (File[] | undefined). Here’s how I revised the code:

    <template>
        <v-file-input  v-model="internalValue" :rules="rules" />
     </template>
    
    <script setup lang="ts">
        const rules = [
            (v: File[] | undefined) => {
                return (v && v.length > 0) || messages.validation.imagePath.required
            },
            (v: File[] | undefined) => {
                console.log(v, 'val') // if you print this you can see you get an array
                if (!v || v.length === 0) return true
                const oversizedFile = v.find((file) => file.size > 5 * 1024 * 1024)
                return !oversizedFile || messages.validation.imagePath.maxSize
            },
            (v: File[] | undefined) => {
                if (!v || v.length === 0) return true
                const invalidTypeFile = v.find((file) => !['image/jpeg', 'image/jpg'].includes(file.type))
                return !invalidTypeFile || messages.validation.imagePath.invalidFormat
            }
        ]
    </script>
    

    this solved the issue for me and it's convenient because you don't have to set validation errors manually