From 7fb6eb882b64bf99a99d00606e54b0e050674206 Mon Sep 17 00:00:00 2001 From: skirtle <65301168+skirtles-code@users.noreply.github.com> Date: Sat, 13 Jul 2024 07:57:37 +0100 Subject: [PATCH] fix(v-model): component v-model modifiers trim and number when cases don't match (#9609) close #4848 close #4850 (based on commits from #4850) Co-authored-by: zhaozhongyu Co-authored-by: Evan You --- .../__tests__/componentEmits.spec.ts | 77 +++++++++++++++++++ packages/runtime-core/src/helpers/useModel.ts | 9 ++- 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/__tests__/componentEmits.spec.ts b/packages/runtime-core/__tests__/componentEmits.spec.ts index 86307275b..e2e9044a1 100644 --- a/packages/runtime-core/__tests__/componentEmits.spec.ts +++ b/packages/runtime-core/__tests__/componentEmits.spec.ts @@ -356,6 +356,83 @@ describe('component: emit', () => { expect(fn2).toHaveBeenCalledWith('two') }) + test('.trim modifier should work with v-model on component for kebab-cased props and camelCased emit', () => { + const Foo = defineComponent({ + render() {}, + created() { + this.$emit('update:firstName', ' one ') + }, + }) + + const fn1 = vi.fn() + + const Comp = () => + h(Foo, { + 'first-name': null, + 'first-nameModifiers': { trim: true }, + 'onUpdate:first-name': fn1, + }) + + render(h(Comp), nodeOps.createElement('div')) + + expect(fn1).toHaveBeenCalledTimes(1) + expect(fn1).toHaveBeenCalledWith('one') + }) + + test('.trim modifier should work with v-model on component for camelCased props and kebab-cased emit', () => { + const Foo = defineComponent({ + render() {}, + created() { + this.$emit('update:model-value', ' one ') + this.$emit('update:first-name', ' two ') + }, + }) + + const fn1 = vi.fn() + const fn2 = vi.fn() + + const Comp = () => + h(Foo, { + modelValue: null, + modelModifiers: { trim: true }, + 'onUpdate:modelValue': fn1, + + firstName: null, + firstNameModifiers: { trim: true }, + 'onUpdate:firstName': fn2, + }) + + render(h(Comp), nodeOps.createElement('div')) + + expect(fn1).toHaveBeenCalledTimes(1) + expect(fn1).toHaveBeenCalledWith('one') + expect(fn2).toHaveBeenCalledTimes(1) + expect(fn2).toHaveBeenCalledWith('two') + }) + + test('.trim modifier should work with v-model on component for mixed cased props and emit', () => { + const Foo = defineComponent({ + render() {}, + created() { + this.$emit('update:base-URL', ' one ') + }, + }) + + const fn1 = vi.fn() + + const Comp = () => + h(Foo, { + 'base-URL': null, + 'base-URLModifiers': { trim: true }, + 'onUpdate:base-URL': fn1, + }) + + render(h(Comp), nodeOps.createElement('div')) + + expect(fn1).toHaveBeenCalledTimes(1) + expect(fn1).toHaveBeenCalledWith('one') + }) + test('.trim and .number modifiers should work with v-model on component', () => { const Foo = defineComponent({ render() {}, diff --git a/packages/runtime-core/src/helpers/useModel.ts b/packages/runtime-core/src/helpers/useModel.ts index 38f004bb5..8e775a4b9 100644 --- a/packages/runtime-core/src/helpers/useModel.ts +++ b/packages/runtime-core/src/helpers/useModel.ts @@ -108,5 +108,10 @@ export function useModel( export const getModelModifiers = ( props: Record, modelName: string, -): Record | undefined => - props[`${modelName === 'modelValue' ? 'model' : modelName}Modifiers`] +): Record | undefined => { + return modelName === 'modelValue' || modelName === 'model-value' + ? props.modelModifiers + : props[`${modelName}Modifiers`] || + props[`${camelize(modelName)}Modifiers`] || + props[`${hyphenate(modelName)}Modifiers`] +}