Subscribe on changes!

select option value attribute is not set if value is equal to text

avatar
Nov 17th 2021

Version

3.2.22

Reproduction link

sfc.vuejs.org/

Steps to reproduce

Inspect the select options and see that the option with value === textContent has no value set.

What is expected?

Regardless of the textContent I expected an option to correctly have the value attribute and not silently remove it.

What is actually happening?

The value attribute is removed.


I have verified that this is not happening in vue2. Reproduction link

If I'm missing some part of the option spec please point me to it. But as far as I am seeing it it is perfectly valid to have an option with value = textContent and I our case needed for e2e testing frameworks like Selenium to select a predefined value.

avatar
Nov 17th 2021

It happens because

  1. We first set the options textContent before the value property

https://github.com/vuejs/vue-next/blob/f454dd62ab689b348902b01f849ca5347e91ffae/packages/runtime-core/src/renderer.ts#L655

  1. then, when attempting to set the value prop, we compare the new, incoming value to the existing one - and only set the property if there's a difference,.

https://github.com/vuejs/vue-next/blob/f454dd62ab689b348902b01f849ca5347e91ffae/packages/runtime-core/src/renderer.ts#L699

and this (no idea why github decided not to inline code for this one link 🤷🏻‍♂️):

https://github.com/vuejs/vue-next/blob/f454dd62ab689b348902b01f849ca5347e91ffae/packages/runtime-dom/src/modules/props.ts?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L34

  1. Problem is: el.value returns the textContent when no value prop is set.

So el.value === newValue is returning true even though there's no value being set yet - but we skip setting it because of the appearant equality between "old" and "new" value

Not sure about the best solution yet - set element Text after setting the value prop isn't gonna work as we do it before explicitly so that <select value> works.

So we might need some edge case handling in patchDOMProp()'s implementation?