vuejs/core

select v-model does not set 'selected' attribute on option with v-for directive using SSR

tirojal opened this issue · 2 comments

Vue version

3.5.12

Link to minimal reproduction

https://play.vuejs.org/#__SSR__eNqFUstOwzAQ/BXLl4BUWsSbKiAB4gAHQIC4YA4l3Ra3jm3Zm1AU5d/Z2E0fCEoiZeKdyWbG64pfWNstC+B9nvrMSYvMAxb2XGiZW+OQVczBiNVs5EzOEpImQgudGe2R4Qe8DFQB7KwRbSWHu7vJdksOlAqkn7OvyeyfK+mwZI9aEOxHOIjQ9CU4inAc4STCKcEb/TTtRf/knBYIuVUDBFqlQ1k2RaQ7PFMPCjJk5U5uhqDOBG9zCN4KMTUWpaFWcSmw3BkZR1prvJfvah5c6mVOwZfq/hS+forX+LKp/K1Y+BBYVWz9n3W9MNmLLudq2oKQLCzTXsyd9lb2gnc4ehrPSI67E280jb0SmjHBM5NbqcDdh4aUpc8C03CU0Hzehhq6AjptPfuAbPpLfeJnTU3wBwceXEm5FhwO3Bgw0tdPdzCj9wVJ8ygUqTeQj+CNKsJoguyy0EOyvaILbm/C4ZV6/OyvZwjat6Eao42yDnrB6UBfbYi+tLvfPQjfCV3z+hu9thho

Steps to reproduce

Click on refresh button.

What is expected?

option with value === '500' should have selected attribute on SSR

What is actually happening?

option receives selected attribute only on CSR, you may see 'xxxxxxxx' option is selected for a moment after pressing 'refresh'

System Info

No response

Any additional comments?

Found similar issue, but in my case it happens only when option have v-for attribute
#5339

and another reproduction:

import { createSSRApp } from 'vue'
import { renderToString } from 'vue/server-renderer'

const appOk = createSSRApp({
	data: () => ({ theValue: '400' }),
	template: `<select v-model="theValue">
			<option value="100">100</option>
			<option value="200">200</option>
			<option value="300">300</option>
			<option value="400">400</option>
		</select>`,
})
const appNotOk = createSSRApp({
	data: () => ({ theValue: '400', allValues: ['100', '200', '300', '400'] }),
	template: `<select v-model="theValue">
			<option
				v-for="possibleValue in allValues"
				:key="possibleValue"
				:value="possibleValue"
			>
				{{ possibleValue }}
			</option>
		</select>`,
})

renderToString(appOk).then((html) => {
	console.log('appOk')
	console.log('-----')
	console.log(html) // <select><option value="100">100</option><option value="200">200</option><option value="300">300</option><option value="400" selected>400</option></select>
	console.log('-----')
	console.log('-----')
})
renderToString(appNotOk).then((html) => {
	console.log('appNotOk')
	console.log('-----')
	console.log(html) //<select><!--[--><option value="100">100</option><option value="200">200</option><option value="300">300</option><option value="400">400</option><!--]--></select>
	console.log('-----')
	console.log('-----')
})

if (child.type === NodeTypes.ELEMENT) {
processOption(child as PlainElementNode)
}

processOption on line 167 is skipped because child.type is not NodeTypes.ELEMENT but NodeTypes.FOR