]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(v-model): component v-model modifiers trim and number when cases don't match...
authorskirtle <65301168+skirtles-code@users.noreply.github.com>
Sat, 13 Jul 2024 06:57:37 +0000 (07:57 +0100)
committerGitHub <noreply@github.com>
Sat, 13 Jul 2024 06:57:37 +0000 (14:57 +0800)
close #4848
close #4850 (based on commits from #4850)

Co-authored-by: zhaozhongyu <zhaozhongyu@xunlei.com>
Co-authored-by: Evan You <evan@vuejs.org>
packages/runtime-core/__tests__/componentEmits.spec.ts
packages/runtime-core/src/helpers/useModel.ts

index 86307275bf8e4dc26b7e92f34c1b98a2e5c177d2..e2e9044a1b4dac3ffb61e6b2cf05c13d26972ef6 100644 (file)
@@ -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() {},
index 38f004bb53528dd4eb8c33ef5bd3038660c6a239..8e775a4b90e1aad0634d60c2b5bbaf6ee2411a18 100644 (file)
@@ -108,5 +108,10 @@ export function useModel(
 export const getModelModifiers = (
   props: Record<string, any>,
   modelName: string,
-): Record<string, boolean> | undefined =>
-  props[`${modelName === 'modelValue' ? 'model' : modelName}Modifiers`]
+): Record<string, boolean> | undefined => {
+  return modelName === 'modelValue' || modelName === 'model-value'
+    ? props.modelModifiers
+    : props[`${modelName}Modifiers`] ||
+        props[`${camelize(modelName)}Modifiers`] ||
+        props[`${hyphenate(modelName)}Modifiers`]
+}