From e4b0a487fca64f6974a6a6a3baefa24ee1a80470 Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 8 Jun 2026 15:16:30 +0200 Subject: [PATCH] feat(date): accept a null modelValue in DatepickerWithRange --- .../components/date/DatepickerWithRange.test.ts | 14 ++++++++++++++ .../src/components/date/DatepickerWithRange.vue | 13 +++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/date/DatepickerWithRange.test.ts b/frontend/src/components/date/DatepickerWithRange.test.ts index 080526957..a165acf1f 100644 --- a/frontend/src/components/date/DatepickerWithRange.test.ts +++ b/frontend/src/components/date/DatepickerWithRange.test.ts @@ -36,4 +36,18 @@ describe('DatepickerWithRange predefined ranges', () => { const last = wrapper.emitted('update:modelValue')?.pop()?.[0] expect(last).toEqual({dateFrom: 'now/M-1M', dateTo: 'now/M'}) }) + + // A cleared range (the Custom option) comes back as null via v-model; the + // modelValue watcher must coerce it, not call null.toISOString(). + it('accepts a null modelValue without crashing', async () => { + const wrapper = mountPicker() + await wrapper.setProps({modelValue: {dateFrom: 'now/w', dateTo: 'now/w+1w'}}) + await wrapper.vm.$nextTick() + expect((wrapper.vm as any).from).toBe('now/w') + + await wrapper.setProps({modelValue: {dateFrom: null, dateTo: null}}) + await wrapper.vm.$nextTick() + expect((wrapper.vm as any).from).toBe('') + expect((wrapper.vm as any).to).toBe('') + }) }) diff --git a/frontend/src/components/date/DatepickerWithRange.vue b/frontend/src/components/date/DatepickerWithRange.vue index c15383007..75cdaf7f5 100644 --- a/frontend/src/components/date/DatepickerWithRange.vue +++ b/frontend/src/components/date/DatepickerWithRange.vue @@ -114,16 +114,17 @@ import DatemathHelp from '@/components/date/DatemathHelp.vue' import {useFlatpickrLanguage} from '@/helpers/useFlatpickrLanguage' const props = defineProps<{ + // null for a side that's been cleared (the Custom option) — emitted, so accepted too. modelValue: { - dateFrom: Date | string, - dateTo: Date | string, + dateFrom: Date | string | null, + dateTo: Date | string | null, }, }>() const emit = defineEmits<{ 'update:modelValue': [value: { - dateFrom: Date | string, - dateTo: Date | string + dateFrom: Date | string | null, + dateTo: Date | string | null }] }>() @@ -149,8 +150,8 @@ const to = ref('') watch( () => props.modelValue, newValue => { - from.value = typeof newValue.dateFrom === 'string' ? newValue.dateFrom : newValue.dateFrom.toISOString() - to.value = typeof newValue.dateTo === 'string' ? newValue.dateTo : newValue.dateTo.toISOString() + from.value = typeof newValue.dateFrom === 'string' ? newValue.dateFrom : (newValue.dateFrom?.toISOString() ?? '') + to.value = typeof newValue.dateTo === 'string' ? newValue.dateTo : (newValue.dateTo?.toISOString() ?? '') // Only set the date back to flatpickr when it's an actual date. // Otherwise flatpickr runs in an endless loop and slows down the browser. const dateFrom = parseDateOrString(from.value, false)