]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-ssr): handle v-model checkbox with true-value binding
authorEvan You <yyx990803@gmail.com>
Tue, 1 Dec 2020 17:43:59 +0000 (12:43 -0500)
committerEvan You <yyx990803@gmail.com>
Tue, 1 Dec 2020 17:43:59 +0000 (12:43 -0500)
packages/compiler-ssr/__tests__/ssrVModel.spec.ts
packages/compiler-ssr/src/transforms/ssrTransformElement.ts
packages/compiler-ssr/src/transforms/ssrVModel.ts

index 18a03b115f4e4291e73b89331d29f2a03d8374ef..21ce80a00bd52bdc006058f73ce31346cecd4a6c 100644 (file)
@@ -49,7 +49,7 @@ describe('ssr: v-model', () => {
     `)
   })
 
-  test('<input type="checkbox"', () => {
+  test('<input type="checkbox">', () => {
     expect(compileWithWrapper(`<input type="checkbox" v-model="bar">`).code)
       .toMatchInlineSnapshot(`
       "const { ssrLooseContain: _ssrLooseContain, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
@@ -81,6 +81,38 @@ describe('ssr: v-model', () => {
         }></div>\`)
       }"
     `)
+
+    expect(
+      compileWithWrapper(
+        `<input type="checkbox" :true-value="foo" :false-value="bar" v-model="baz">`
+      ).code
+    ).toMatchInlineSnapshot(`
+      "const { ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
+
+      return function ssrRender(_ctx, _push, _parent, _attrs) {
+        _push(\`<div\${
+          _ssrRenderAttrs(_attrs)
+        }><input type=\\"checkbox\\"\${
+          (_ssrLooseEqual(_ctx.baz, _ctx.foo)) ? \\" checked\\" : \\"\\"
+        }></div>\`)
+      }"
+    `)
+
+    expect(
+      compileWithWrapper(
+        `<input type="checkbox" true-value="foo" false-value="bar" v-model="baz">`
+      ).code
+    ).toMatchInlineSnapshot(`
+      "const { ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
+
+      return function ssrRender(_ctx, _push, _parent, _attrs) {
+        _push(\`<div\${
+          _ssrRenderAttrs(_attrs)
+        }><input type=\\"checkbox\\"\${
+          (_ssrLooseEqual(_ctx.baz, \\"foo\\")) ? \\" checked\\" : \\"\\"
+        }></div>\`)
+      }"
+    `)
   })
 
   test('<textarea>', () => {
index cfc02530fa5ccab2022725c788ac2dfa18db9211..861446d562db141e8888d9764ec6ac9f04eb952f 100644 (file)
@@ -25,7 +25,8 @@ import {
   isBindKey,
   createSequenceExpression,
   InterpolationNode,
-  isStaticExp
+  isStaticExp,
+  AttributeNode
 } from '@vue/compiler-dom'
 import {
   escapeHtml,
@@ -159,6 +160,10 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
 
     for (let i = 0; i < node.props.length; i++) {
       const prop = node.props[i]
+      // ignore true-value/false-value on input
+      if (node.tag === 'input' && isTrueFalseValue(prop)) {
+        continue
+      }
       // special cases with children override
       if (prop.type === NodeTypes.DIRECTIVE) {
         if (prop.name === 'html' && prop.exp) {
@@ -306,6 +311,19 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
   }
 }
 
+function isTrueFalseValue(prop: DirectiveNode | AttributeNode) {
+  if (prop.type === NodeTypes.DIRECTIVE) {
+    return (
+      prop.name === 'bind' &&
+      prop.arg &&
+      isStaticExp(prop.arg) &&
+      (prop.arg.content === 'true-value' || prop.arg.content === 'false-value')
+    )
+  } else {
+    return prop.name === 'true-value' || prop.name === 'false-value'
+  }
+}
+
 function isTextareaWithValue(
   node: PlainElementNode,
   prop: DirectiveNode
index f23c62fedb49433efd5c6c8e28f93b0a80b4ab1f..589ef6a8650f32e2160cf012267b387ae59579e6 100644 (file)
@@ -71,19 +71,36 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
               ]
               break
             case 'checkbox':
-              res.props = [
-                createObjectProperty(
-                  `checked`,
-                  createConditionalExpression(
-                    createCallExpression(`Array.isArray`, [model]),
-                    createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
+              const trueValueBinding = findProp(node, 'true-value')
+              if (trueValueBinding) {
+                const trueValue =
+                  trueValueBinding.type === NodeTypes.ATTRIBUTE
+                    ? JSON.stringify(trueValueBinding.value!.content)
+                    : trueValueBinding.exp!
+                res.props = [
+                  createObjectProperty(
+                    `checked`,
+                    createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
                       model,
-                      value
-                    ]),
-                    model
+                      trueValue
+                    ])
                   )
-                )
-              ]
+                ]
+              } else {
+                res.props = [
+                  createObjectProperty(
+                    `checked`,
+                    createConditionalExpression(
+                      createCallExpression(`Array.isArray`, [model]),
+                      createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
+                        model,
+                        value
+                      ]),
+                      model
+                    )
+                  )
+                ]
+              }
               break
             case 'file':
               context.onError(