diff --git a/src/runtime/components/Input.vue b/src/runtime/components/Input.vue index 175828b0..20d3db13 100644 --- a/src/runtime/components/Input.vue +++ b/src/runtime/components/Input.vue @@ -82,7 +82,7 @@ const props = withDefaults(defineProps(), { const emits = defineEmits() const slots = defineSlots() -const [modelValue, modelModifiers] = defineModel() +const [modelValue, modelModifiers] = defineModel() const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled, emitFormFocus, ariaAttrs } = useFormField(props, { deferInputValidation: true }) const { orientation, size: buttonGroupSize } = useButtonGroup(props) @@ -111,15 +111,19 @@ function autoFocus() { } // Custom function to handle the v-model properties -function updateInput(value: string) { +function updateInput(value: string | null) { if (modelModifiers.trim) { - value = value.trim() + value = value?.trim() ?? null } if (modelModifiers.number || props.type === 'number') { value = looseToNumber(value) } + if (modelModifiers.nullify) { + value ||= null + } + modelValue.value = value emitFormInput() } diff --git a/src/runtime/components/Textarea.vue b/src/runtime/components/Textarea.vue index b1d07609..e1ee8d66 100644 --- a/src/runtime/components/Textarea.vue +++ b/src/runtime/components/Textarea.vue @@ -74,7 +74,7 @@ const props = withDefaults(defineProps(), { defineSlots() const emits = defineEmits() -const [modelValue, modelModifiers] = defineModel() +const [modelValue, modelModifiers] = defineModel() const { emitFormFocus, emitFormBlur, emitFormInput, emitFormChange, size, color, id, name, highlight, disabled, ariaAttrs } = useFormField(props, { deferInputValidation: true }) @@ -94,15 +94,19 @@ function autoFocus() { } // Custom function to handle the v-model properties -function updateInput(value: string) { +function updateInput(value: string | null) { if (modelModifiers.trim) { - value = value.trim() + value = value?.trim() ?? null } if (modelModifiers.number) { value = looseToNumber(value) } + if (modelModifiers.nullify) { + value ||= null + } + modelValue.value = value emitFormInput() } diff --git a/test/components/Input.spec.ts b/test/components/Input.spec.ts index 7c94ee67..9b5f5d41 100644 --- a/test/components/Input.spec.ts +++ b/test/components/Input.spec.ts @@ -52,7 +52,8 @@ describe('Input', () => { it.each([ ['with .trim modifier', { props: { modelModifiers: { trim: true } } }, { input: 'input ', expected: 'input' }], ['with .number modifier', { props: { modelModifiers: { number: true } } }, { input: '42', expected: 42 }], - ['with .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' }] + ['with .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' }], + ['with .nullify modifier', { props: { modelModifiers: { nullify: true } } }, { input: '', expected: null }] ])('%s works', async (_nameOrHtml: string, options: { props?: any, slots?: any }, spec: { input: any, expected: any }) => { const wrapper = mount(Input, { ...options diff --git a/test/components/Textarea.spec.ts b/test/components/Textarea.spec.ts index 7eba2caf..c960f215 100644 --- a/test/components/Textarea.spec.ts +++ b/test/components/Textarea.spec.ts @@ -35,7 +35,8 @@ describe('Textarea', () => { it.each([ ['with .trim modifier', { props: { modelModifiers: { trim: true } } }, { input: 'input ', expected: 'input' }], ['with .number modifier', { props: { modelModifiers: { number: true } } }, { input: '42', expected: 42 }], - ['with .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' }] + ['with .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' }], + ['with .nullify modifier', { props: { modelModifiers: { nullify: true } } }, { input: '', expected: null }] ])('%s works', async (_nameOrHtml: string, options: { props?: any, slots?: any }, spec: { input: any, expected: any }) => { const wrapper = mount(Textarea, { ...options