fix(ssr): handle initial selected state for select with v-model + v-for/v-if option (#13487)
close #13486
This commit is contained in:
parent
f3479aac96
commit
15520954f9
|
@ -166,6 +166,132 @@ describe('ssr: v-model', () => {
|
||||||
_push(\`</optgroup></select></div>\`)
|
_push(\`</optgroup></select></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
compileWithWrapper(`
|
||||||
|
<select multiple v-model="model">
|
||||||
|
<optgroup>
|
||||||
|
<option v-for="item in items" :value="item">{{item}}</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>`).code,
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require("vue/server-renderer")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup><!--[-->\`)
|
||||||
|
_ssrRenderList(_ctx.items, (item) => {
|
||||||
|
_push(\`<option\${
|
||||||
|
_ssrRenderAttr("value", item)
|
||||||
|
}\${
|
||||||
|
(_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
|
||||||
|
? _ssrLooseContain(_ctx.model, item)
|
||||||
|
: _ssrLooseEqual(_ctx.model, item))) ? " selected" : ""
|
||||||
|
}>\${
|
||||||
|
_ssrInterpolate(item)
|
||||||
|
}</option>\`)
|
||||||
|
})
|
||||||
|
_push(\`<!--]--></optgroup></select></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
compileWithWrapper(`
|
||||||
|
<select multiple v-model="model">
|
||||||
|
<optgroup>
|
||||||
|
<option v-if="true" :value="item">{{item}}</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>`).code,
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup>\`)
|
||||||
|
if (true) {
|
||||||
|
_push(\`<option\${
|
||||||
|
_ssrRenderAttr("value", _ctx.item)
|
||||||
|
}\${
|
||||||
|
(_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
|
||||||
|
? _ssrLooseContain(_ctx.model, _ctx.item)
|
||||||
|
: _ssrLooseEqual(_ctx.model, _ctx.item))) ? " selected" : ""
|
||||||
|
}>\${
|
||||||
|
_ssrInterpolate(_ctx.item)
|
||||||
|
}</option>\`)
|
||||||
|
} else {
|
||||||
|
_push(\`<!---->\`)
|
||||||
|
}
|
||||||
|
_push(\`</optgroup></select></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
compileWithWrapper(`
|
||||||
|
<select multiple v-model="model">
|
||||||
|
<optgroup>
|
||||||
|
<template v-if="ok">
|
||||||
|
<option v-for="item in items" :value="item">{{item}}</option>
|
||||||
|
</template>
|
||||||
|
</optgroup>
|
||||||
|
</select>`).code,
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require("vue/server-renderer")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup>\`)
|
||||||
|
if (_ctx.ok) {
|
||||||
|
_push(\`<!--[-->\`)
|
||||||
|
_ssrRenderList(_ctx.items, (item) => {
|
||||||
|
_push(\`<option\${
|
||||||
|
_ssrRenderAttr("value", item)
|
||||||
|
}\${
|
||||||
|
(_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
|
||||||
|
? _ssrLooseContain(_ctx.model, item)
|
||||||
|
: _ssrLooseEqual(_ctx.model, item))) ? " selected" : ""
|
||||||
|
}>\${
|
||||||
|
_ssrInterpolate(item)
|
||||||
|
}</option>\`)
|
||||||
|
})
|
||||||
|
_push(\`<!--]-->\`)
|
||||||
|
} else {
|
||||||
|
_push(\`<!---->\`)
|
||||||
|
}
|
||||||
|
_push(\`</optgroup></select></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
compileWithWrapper(`
|
||||||
|
<select multiple v-model="model">
|
||||||
|
<optgroup>
|
||||||
|
<template v-for="item in items" :value="item">
|
||||||
|
<option v-if="item===1" :value="item">{{item}}</option>
|
||||||
|
</template>
|
||||||
|
</optgroup>
|
||||||
|
</select>`).code,
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require("vue/server-renderer")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup><!--[-->\`)
|
||||||
|
_ssrRenderList(_ctx.items, (item) => {
|
||||||
|
_push(\`<!--[-->\`)
|
||||||
|
if (item===1) {
|
||||||
|
_push(\`<option\${
|
||||||
|
_ssrRenderAttr("value", item)
|
||||||
|
}\${
|
||||||
|
(_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
|
||||||
|
? _ssrLooseContain(_ctx.model, item)
|
||||||
|
: _ssrLooseEqual(_ctx.model, item))) ? " selected" : ""
|
||||||
|
}>\${
|
||||||
|
_ssrInterpolate(item)
|
||||||
|
}</option>\`)
|
||||||
|
} else {
|
||||||
|
_push(\`<!---->\`)
|
||||||
|
}
|
||||||
|
_push(\`<!--]-->\`)
|
||||||
|
})
|
||||||
|
_push(\`<!--]--></optgroup></select></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<input type="radio">', () => {
|
test('<input type="radio">', () => {
|
||||||
|
|
|
@ -39,6 +39,18 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const processSelectChildren = (children: TemplateChildNode[]) => {
|
||||||
|
children.forEach(child => {
|
||||||
|
if (child.type === NodeTypes.ELEMENT) {
|
||||||
|
processOption(child as PlainElementNode)
|
||||||
|
} else if (child.type === NodeTypes.FOR) {
|
||||||
|
processSelectChildren(child.children)
|
||||||
|
} else if (child.type === NodeTypes.IF) {
|
||||||
|
child.branches.forEach(b => processSelectChildren(b.children))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function processOption(plainNode: PlainElementNode) {
|
function processOption(plainNode: PlainElementNode) {
|
||||||
if (plainNode.tag === 'option') {
|
if (plainNode.tag === 'option') {
|
||||||
if (plainNode.props.findIndex(p => p.name === 'selected') === -1) {
|
if (plainNode.props.findIndex(p => p.name === 'selected') === -1) {
|
||||||
|
@ -65,9 +77,7 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if (plainNode.tag === 'optgroup') {
|
} else if (plainNode.tag === 'optgroup') {
|
||||||
plainNode.children.forEach(option =>
|
processSelectChildren(plainNode.children)
|
||||||
processOption(option as PlainElementNode),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,18 +173,7 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
checkDuplicatedValue()
|
checkDuplicatedValue()
|
||||||
node.children = [createInterpolation(model, model.loc)]
|
node.children = [createInterpolation(model, model.loc)]
|
||||||
} else if (node.tag === 'select') {
|
} else if (node.tag === 'select') {
|
||||||
const processChildren = (children: TemplateChildNode[]) => {
|
processSelectChildren(node.children)
|
||||||
children.forEach(child => {
|
|
||||||
if (child.type === NodeTypes.ELEMENT) {
|
|
||||||
processOption(child as PlainElementNode)
|
|
||||||
} else if (child.type === NodeTypes.FOR) {
|
|
||||||
processChildren(child.children)
|
|
||||||
} else if (child.type === NodeTypes.IF) {
|
|
||||||
child.branches.forEach(b => processChildren(b.children))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
processChildren(node.children)
|
|
||||||
} else {
|
} else {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(
|
createDOMCompilerError(
|
||||||
|
|
Loading…
Reference in New Issue