patchProp(el, 'value', null, obj)
expect(el.value).toBe(obj.toString())
expect((el as any)._value).toBe(obj)
+
+ const option = document.createElement('option')
+ patchProp(option, 'textContent', null, 'foo')
+ expect(option.value).toBe('foo')
+ expect(option.getAttribute('value')).toBe(null)
+ patchProp(option, 'value', null, 'foo')
+ expect(option.value).toBe('foo')
+ expect(option.getAttribute('value')).toBe('foo')
})
test('value for custom elements', () => {
return
}
+ const tag = el.tagName
+
if (
key === 'value' &&
- el.tagName !== 'PROGRESS' &&
+ tag !== 'PROGRESS' &&
// custom elements may use _value internally
- !el.tagName.includes('-')
+ !tag.includes('-')
) {
// store value as _value as well since
// non-string values will be stringified.
el._value = value
+ // #4956: <option> value will fallback to its text content so we need to
+ // compare against its attribute value instead.
+ const oldValue = tag === 'OPTION' ? el.getAttribute('value') : el.value
const newValue = value == null ? '' : value
- if (
- el.value !== newValue ||
- // #4956: always set for OPTION elements because its value falls back to
- // textContent if no value attribute is present. And setting .value for
- // OPTION has no side effect
- el.tagName === 'OPTION'
- ) {
+ if (oldValue !== newValue) {
el.value = newValue
}
if (value == null) {
// do not warn if value is auto-coerced from nullish values
if (__DEV__ && !needRemove) {
warn(
- `Failed setting prop "${key}" on <${el.tagName.toLowerCase()}>: ` +
+ `Failed setting prop "${key}" on <${tag.toLowerCase()}>: ` +
`value ${value} is invalid.`,
e
)