N
Nuxt4mo ago
Uchuu

When I select a new date, the button does not reflect the new date - it stays as today's date.

<FormFieldWrapper title="Prize Deadline" description="When is the closing date for this prize?"> <UFormField name="spec"> <UPopover> <UButton color="neutral" variant="subtle" icon="i-lucide-calendar"> {{ formattedCalendarDate }} </UButton> <template #content> <UCalendar v-model="calendarValue" class="p-2" /> </template> </UPopover> </UFormField> </FormFieldWrapper>
8 Replies
kapa.ai
kapa.ai4mo ago
Hi @Uchuu. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- The issue you're experiencing—where the button does not update to reflect the newly selected date—typically happens when the displayed value (formattedCalendarDate) is not properly reactive to changes in calendarValue. According to the official Nuxt UI Calendar and DatePicker example, the displayed date should be computed from the same reactive value that is bound to the calendar's v-model prop. Here’s how it’s done in the documentation:
<script setup lang="ts">
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'

const df = new DateFormatter('en-US', {
dateStyle: 'medium'
})

const modelValue = shallowRef(new CalendarDate(2022, 1, 10))
</script>

<template>
<UPopover>
<UButton color="neutral" variant="subtle" icon="i-lucide-calendar">
{{ modelValue ? df.format(modelValue.toDate(getLocalTimeZone())) : 'Select a date' }}
</UButton>

<template #content>
<UCalendar v-model="modelValue" class="p-2" />
</template>
</UPopover>
</template>
<script setup lang="ts">
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'

const df = new DateFormatter('en-US', {
dateStyle: 'medium'
})

const modelValue = shallowRef(new CalendarDate(2022, 1, 10))
</script>

<template>
<UPopover>
<UButton color="neutral" variant="subtle" icon="i-lucide-calendar">
{{ modelValue ? df.format(modelValue.toDate(getLocalTimeZone())) : 'Select a date' }}
</UButton>

<template #content>
<UCalendar v-model="modelValue" class="p-2" />
</template>
</UPopover>
</template>
Key points: - The button label uses the same modelValue that is bound to the calendar. - The formatted date is computed directly from modelValue, ensuring reactivity. How to fix your code: 1. Make sure calendarValue is a reactive reference (e.g., ref or shallowRef). 2. Compute formattedCalendarDate as a computed property that depends on calendarValue. Example fix:
<script setup lang="ts">
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'
import { ref, computed } from 'vue'

const df = new DateFormatter('en-US', { dateStyle: 'medium' })
const calendarValue = ref(new CalendarDate(2022, 1, 10))

const formattedCalendarDate = computed(() =>
calendarValue.value
? df.format(calendarValue.value.toDate(getLocalTimeZone()))
: 'Select a date'
)
</script>
<template>
<UPopover>
<UButton color="neutral" variant="subtle" icon="i-lucide-calendar">
{{ formattedCalendarDate }}
</UButton>
<template #content>
<UCalendar v-model="calendarValue" class="p-2" />
</template>
</UPopover>
</template>
<script setup lang="ts">
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'
import { ref, computed } from 'vue'

const df = new DateFormatter('en-US', { dateStyle: 'medium' })
const calendarValue = ref(new CalendarDate(2022, 1, 10))

const formattedCalendarDate = computed(() =>
calendarValue.value
? df.format(calendarValue.value.toDate(getLocalTimeZone()))
: 'Select a date'
)
</script>
<template>
<UPopover>
<UButton color="neutral" variant="subtle" icon="i-lucide-calendar">
{{ formattedCalendarDate }}
</UButton>
<template #content>
<UCalendar v-model="calendarValue" class="p-2" />
</template>
</UPopover>
</template>
This approach ensures that when you select a new date in the calendar, the button label updates accordingly, just as shown in the official DatePicker example. If you follow this pattern and still experience issues, double-check that your calendarValue and formattedCalendarDate are set up as shown above and that you are not accidentally using a non-reactive value or missing a computed property for formatting the date.
As a DatePicker - Nuxt UI Calendar ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@1035470271441805353> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Uchuu
UchuuOP4mo ago
const modelValue = shallowRef(new CalendarDate(2022, 1, 10)) type PrizeSchema = v.InferOutput<typeof prizeSchema> const prizeState = reactive<PrizeSchema>({ prizeName: '', desc: '', spec: '', deadline: modelValue.value.toDate(getLocalTimeZone()), bounty: 0 }) Why is deadline not being updated when modelValue is being changed? <FormFieldWrapper title="Prize Deadline" description="When is the closing date for this prize?"> <UFormField name="deadline"> <UPopover> <UButton color="neutral" variant="subtle" icon="i-lucide-calendar"> {{ modelValue ? df.format(modelValue.toDate(getLocalTimeZone())) : 'Select a date' }} </UButton> <template #content> <UCalendar v-model="modelValue" class="p-2" /> </template> </UPopover> </UFormField> </FormFieldWrapper> const createPrize = async ({ data }: FormSubmitEvent<PrizeSchema>) => { console.log(data.prizeName); console.log(data.desc); console.log(data.deadline); console.log(data.bounty); console.log(data.spec) } It is still printing the default specified date @kapa.ai const modelValue = shallowRef(new CalendarDate(2022, 1, 10)) type PrizeSchema = v.InferOutput<typeof prizeSchema> const prizeState = reactive<PrizeSchema>({ prizeName: '', desc: '', spec: '', deadline: modelValue.value.toDate(getLocalTimeZone()), bounty: 0 }) Why is deadline not being updated when modelValue is being changed? <FormFieldWrapper title="Prize Deadline" description="When is the closing date for this prize?"> <UFormField name="deadline"> <UPopover> <UButton color="neutral" variant="subtle" icon="i-lucide-calendar"> {{ modelValue ? df.format(modelValue.toDate(getLocalTimeZone())) : 'Select a date' }} </UButton> <template ⁠content> <UCalendar v-model="modelValue" class="p-2" /> </template> </UPopover> </UFormField> </FormFieldWrapper> const createPrize = async ({ data }: FormSubmitEvent<PrizeSchema>) => { console.log(data.prizeName); console.log(data.desc); console.log(data.deadline); console.log(data.bounty); console.log(data.spec) } It is still printing the default specified date
kapa.ai
kapa.ai4mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The reason prizeState.deadline is not being updated when modelValue changes is because you are only assigning the initial value of modelValue.value.toDate(getLocalTimeZone()) to deadline when you create the prizeState object. This means deadline is set once, and does not stay in sync with modelValue after that. In Vue's reactivity system, assigning a value like this:
deadline: modelValue.value.toDate(getLocalTimeZone())
deadline: modelValue.value.toDate(getLocalTimeZone())
copies the value at that moment. It does not create a reactive link between modelValue and prizeState.deadline. So, when modelValue changes, prizeState.deadline remains unchanged. How to keep them in sync? You need to explicitly update prizeState.deadline whenever modelValue changes. The standard way to do this in Vue 3 (and Nuxt 3) is to use a watch:
watch(modelValue, (newVal) => {
prizeState.deadline = newVal.toDate(getLocalTimeZone())
})
watch(modelValue, (newVal) => {
prizeState.deadline = newVal.toDate(getLocalTimeZone())
})
This will ensure that every time the user selects a new date, prizeState.deadline is updated accordingly. This pattern is consistent with how Vue reactivity works, as described in the knowledge sources: reactivity is not "magically" deep or cross-linked unless you set it up explicitly, especially when dealing with objects and references between them. You must use a watcher or computed property to keep values in sync when you want this behavior [Nuxt3: emitting an input value from a sign up form Part 3]. Summary:
- Initial assignment only sets the value once. - Use a watcher to keep prizeState.deadline in sync with modelValue. If you need a code example, let me know! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@1035470271441805353> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Uchuu
UchuuOP4mo ago
Where do I put watch(modelValue, (newVal) => { prizeState.deadline = newVal.toDate(getLocalTimeZone()) }) Just in my sciprt tag? @kapa.ai
kapa.ai
kapa.ai4mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Yes, you should place the watch function inside your <script setup> block. In Nuxt 3 and Vue 3, all reactivity-related code, including watchers, should be declared within the <script setup> context to ensure proper lifecycle handling and reactivity. Here’s how you can do it:
<script setup lang="ts">
import { ref, shallowRef, reactive, watch } from 'vue'
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'

const modelValue = shallowRef(new CalendarDate(2022, 1, 10))

const prizeState = reactive({
// ...other fields
deadline: modelValue.value.toDate(getLocalTimeZone())
})

// Keep deadline in sync with modelValue
watch(modelValue, (newVal) => {
prizeState.deadline = newVal.toDate(getLocalTimeZone())
})
</script>
<script setup lang="ts">
import { ref, shallowRef, reactive, watch } from 'vue'
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'

const modelValue = shallowRef(new CalendarDate(2022, 1, 10))

const prizeState = reactive({
// ...other fields
deadline: modelValue.value.toDate(getLocalTimeZone())
})

// Keep deadline in sync with modelValue
watch(modelValue, (newVal) => {
prizeState.deadline = newVal.toDate(getLocalTimeZone())
})
</script>
This approach is consistent with Nuxt and Vue best practices, as shown in the official documentation and examples, where watchers are placed inside the <script setup> block to react to changes in reactive variables [Data Fetching: watch option]. So, just add the watch call in your <script setup>—no special placement is needed beyond that. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@1035470271441805353> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?