diff --git a/.changeset/healthy-peaches-poke.md b/.changeset/healthy-peaches-poke.md new file mode 100644 index 000000000..5de8ec22a --- /dev/null +++ b/.changeset/healthy-peaches-poke.md @@ -0,0 +1,5 @@ +--- +'vee-validate': patch +--- + +fix: respect model modifiers when emitting the value closes #4333 diff --git a/packages/vee-validate/src/useField.ts b/packages/vee-validate/src/useField.ts index 44c9b823a..066f17464 100644 --- a/packages/vee-validate/src/useField.ts +++ b/packages/vee-validate/src/useField.ts @@ -263,8 +263,10 @@ function _useField( validateValidStateOnly(); } + const vm = getCurrentInstance(); + function setValue(newValue: TValue, shouldValidate = true) { - value.value = newValue; + value.value = vm && syncVModel ? applyModelModifiers(newValue, vm.props.modelModifiers) : newValue; const validateFn = shouldValidate ? validateWithStateMutation : validateValidStateOnly; validateFn(); } @@ -583,7 +585,7 @@ function useVModel({ prop, value, handleChange }: ModelOpts Promise, }; } -export function applyModelModifiers(value: unknown, modifiers: unknown) { +export function applyModelModifiers(value: TValue, modifiers: unknown): TValue { if (!isObject(modifiers)) { return value; } if (modifiers.number) { - return toNumber(value as string); + return toNumber(value as string) as TValue; } return value; diff --git a/packages/vee-validate/tests/useField.spec.ts b/packages/vee-validate/tests/useField.spec.ts index 7230563e0..76d4cc114 100644 --- a/packages/vee-validate/tests/useField.spec.ts +++ b/packages/vee-validate/tests/useField.spec.ts @@ -637,6 +637,51 @@ describe('useField()', () => { expect(input?.value).toBe('test'); }); + // #4333 + test('should emit modified values with model modifiers being applied as a prop', async () => { + const model = ref(''); + const InputComponent = defineComponent({ + props: { + modelValue: String, + modelModifiers: null, + }, + setup() { + const { value, errorMessage } = useField('field', undefined, { syncVModel: true }); + + return { + value, + errorMessage, + }; + }, + template: ` + + `, + }); + + const onModelUpdated = vi.fn(); + + mountWithHoc({ + components: { + InputComponent, + }, + setup() { + return { + onModelUpdated, + model, + }; + }, + template: ` + + `, + }); + + const input = document.querySelector('input'); + + setValue(input as any, '123'); + await flushPromises(); + expect(onModelUpdated).toHaveBeenLastCalledWith(123); + }); + test('can disable model events', async () => { const model = ref(''); const InputComponent = defineComponent({