vue.jsnuxt.jszodvue-reactivity

Nuxt + Zod: input type="file" does not display the file name on the first selection


I'm working on a Nuxt project using VueJS and Zod for form validation, and one field is a input type="file". The issue is that, on the first file selection, the input does not display the file name, although state.file updates correctly, and Zod performs the validation as expected. Similarly, if I select a file of a different type, the input still does not display the file name, although state.file has been updated.

What’s important is that on each subsequent file selection of the same type (whether it’s the same file or a different one), the file name displays correctly. The issue only occurs on the initial file selection or when switching to a file of a different type.

<template>
  <UForm :state="state" :schema="schema" @submit="onSubmit" class="space-y-4">
    <UFormGroup label="File:" name="file">
      <UInput type="file" @change="onSelectFile"/>
    </UFormGroup>
    <UButton type="submit">Submit</UButton>
  </UForm>
</template>

<script setup lang="ts">
import { reactive } from 'vue';
import { z } from 'zod';

function onSelectFile(files: FileList) {
  state.file = files[0];
}

const state = reactive({
  file: undefined,
});

const schema = z.object({
  file: z.any()
    .refine(() => state.file?.name.split('.').pop() === 'png', 'Must be .png'),
});

function onSubmit() {
  console.log(state);
}
</script>

I found that adding a two-way binding with a ref fixes the issue:

<UFormGroup label="File:" name="file">
  <UInput type="file" @change="onSelectFile" v-model="fileName"/>
</UFormGroup>

const fileName = ref();

With this approach, the file name displays correctly on the first selection and when switching to a different file type. However, I'd like to avoid this workaround. Why doesn’t the file name display in the input on the first selection or when switching to a different file type, and how can I make it display immediately without the extra ref?


Solution

  • I found that the issue was actually with the UInput component. This has been resolved in @nuxt/ui v2.18.5. After updating to this version, the file name displays correctly on the first selection and when switching file types, even without needing the extra ref. Simply update @nuxt/ui to v2.18.5 or later to fix this issue.