nuxt / nuxt/ui

[UInputDate] Zod validation not triggering when value is updated via UCalendar (DatePicker mode)

Open
#5,920 4 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
6.9k
Forks
1.1k
Avg merge
1d 7h
Merged PRs (30d)
57

Description

Environment
Operating system Linux 6.6.87.2-microsoft-standard-WSL2
CPU AMD Ryzen 5 3600 6-Core Processor (8 cores)
Node.js version v24.13.0
nuxt/cli version 3.31.3
Package manager pnpm@10.26.1
Nuxt version 4.2.2
Nitro version 2.12.9
Builder vite@7.3.0
Config compatibilityDate, css, devtools, eslint, modules, routeRules
Modules @nuxt/eslint@1.12.1, @nuxt/ui@4.4.0, @nuxt/a11y@1.0.0-alpha.1, @nuxt/test-utils@3.23.0
Is this bug related to Nuxt or Vue?

Nuxt

Package

v4.x

Version

v4.4.0

Reproduction

Can't reproduce on codesandbox (troubleshooting to install latest Nuxt/Nuxt UI versions)

<script setup lang="ts">
import { z } from 'zod'
import { CalendarDate } from '@internationalized/date'
import type { FormSubmitEvent } from '#ui/types'

const schema = z.object({
  date: z.custom<CalendarDate>(
    (val) => val && typeof val === 'object' && 'toDate' in val,
    { message: 'Invalid date' }
  )
  .transform((calendarDate) => calendarDate.toDate('UTC'))
  .pipe(
    z.date().max(new Date(), { message: "Too young!" })
  )
})

type Schema = z.output<typeof schema>

const state = reactive({
  date: undefined,
  range: undefined
})

const submittedData = ref<Schema | null>(null)
const inputDate = useTemplateRef('inputDate')

async function onSubmit(event: FormSubmitEvent<Schema>) {
  submittedData.value = event.data
}

const { emitFormInput } = useFormField({ name: "date" })

function onUpdate(open: boolean) {
  if (!open) {
    emitFormInput()
    console.log('Calendar closed ' + open);
  }
}
</script>

<template>
  <UPage>
    <UPageHeader
      title="InputDate Test"
      description="Testing Nuxt UI InputDate component with Zod validation."
      :links="[{ label: 'Back to Home', to: '/', icon: 'i-lucide-arrow-left', color: 'neutral', variant: 'ghost' }]"
    />

    <UPageBody>
      <UForm
        :schema="schema"
        :state="state"
        class="max-w-xl space-y-8"
        @submit="onSubmit"
      >
        <UFormField
          label="Single Date Selection"
          name="date"
          description="Select a single date using UInputDate"
          required
        >
          <UInputDate ref="inputDate" v-model="state.date">
    <template #trailing>
      <UPopover :reference="inputDate?.inputsRef[3]?.$el" @update:open="onUpdate">
        <UButton
          color="neutral"
          variant="link"
          size="sm"
          icon="i-lucide-calendar"
          aria-label="Select a date"
          class="px-0"
        />

        <template #content>
          <UCalendar v-model="state.date" class="p-2" />
        </template>
      </UPopover>
    </template>
  </UInputDate>

        </UFormField>

        <div class="flex items-center gap-3">
          <UButton type="submit">
            Submit Form
          </UButton>
          <UButton
            color="neutral"
            variant="outline"
            @click="state.date = undefined; state.range = undefined; submittedData = null"
          >
            Reset
          </UButton>
        </div>
      </UForm>

      <div v-if="submittedData" class="mt-12 p-6 rounded-lg border border-gray-200 dark:border-gray-800 bg-gray-50 dark:bg-gray-900/50">
        <h4 class="text-sm font-bold uppercase tracking-wider text-gray-500 mb-4">Submitted Data</h4>
        <pre class="text-sm overflow-auto">{{ JSON.stringify(submittedData, null, 2) }}</pre>
      </div>
    </UPageBody>
  </UPage>
</template>
Description

I am encountering an issue with form validation when using the UInputDate component configured as a DatePicker (with UPopover and UCalendar inside the #trailing slot), as seen in the official documentation examples.

When the date is typed manually into the input field, the Zod schema validation triggers correctly. However, when the date is selected via the UCalendar inside the popover, the v-model updates visually, but the UForm validation does not seem to catch the change event, leaving the field in an invalid state or not clearing existing errors.

It seems the UInputDate does not emit the necessary change or blur events to the parent UForm when the value is mutated programmatically via the internal UCalendar.

Additional context

I try to use emitFormInput because of this issue: https://github.com/nuxt/ui/issues/4803

Logs

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provided UInputDate, UCalendar, UForm, and useFormField reproduction, then inspect how the calendar update reaches form validation. Compare manual input events with the UCalendar v-model update and check whether the field receives the needed validation event. Done means selecting a date through the popover updates or clears the Zod validation state without the workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.