4

When setting an input element's type to hidden, and it's value to an empty string, it seems to revert to a previous non-empty value. Can someone please explain why the input value reverts in console log instances 2 and 6 below?

var el   = document.getElementById('input');
el.type  = 'text';
el.value = '';
console.log('1', el.value);
el.type  = 'hidden';
console.log('2', el.value);

el.type  = 'text';
el.value = 'hello';
console.log('3', el.value);
el.type  = 'hidden';
console.log('4', el.value);

el.type  = 'text';
el.value = '';
console.log('5', el.value);
el.type  = 'hidden';
console.log('6', el.value);
<input id="input" type="hidden" value="test">
  • 1
    If you log just `el` before the 5th log it still shows value as set to `hello` as well. – pilchard Feb 28 '23 at 21:55
  • 1
    Does this answer your question? [Why doesn't the value attribute of the input change?](https://stackoverflow.com/questions/10346471/why-doesnt-the-value-attribute-of-the-input-change) – pilchard Feb 28 '23 at 21:55
  • 1
    as per the duplicate, if you use `el.setAttribute('value', '');` the behaviour is resolved. – pilchard Feb 28 '23 at 21:57
  • The dupe target doesn't really answer my questions since (a) I'm not looking at the attribute `value`, but setting the dom property `value` directly as you can see. I am aware they are two different things. And I'm inspecting the same property. Why should the property change after changing the `type` property? And why should it *only change* when it's an empty string, but persist when it's a non-empty string? This seems nonsensical. – But those new buttons though.. Feb 28 '23 at 22:00
  • To be clear - that guy is setting `el.value` and wondering why it doesn't reflect in the attribute visible in his web inspector - which is not what I'm asking here. – But those new buttons though.. Feb 28 '23 at 22:03
  • 1
    What seems to be happening is that when you set `el.value` on a hidden input, it also sets the attribute *unless* you set it to an empty string. If you inspect the element in DevTools, you can see the attribute changing. – Barmar Feb 28 '23 at 22:03
  • I would hazard a guess that changing type causes it to be re-evaluated by the the DOM and the initial attribute value re-applied. if you change type and *then* set value the behaviour also disappears – pilchard Feb 28 '23 at 22:03
  • 2
    I've been searching MDN and the HTML standards trying to find justification for this. – Barmar Feb 28 '23 at 22:04
  • Also please avoid using gendered descriptors when referring to other users. – pilchard Feb 28 '23 at 22:04
  • @pilchard - That's what I was thinking too, but if that was the case, console log #6 should revert back to the attribute value `test`. Instead it reverts back to hello. And this still doesn't explain why the behaviour only happens when an empty string is in question. – But those new buttons though.. Feb 28 '23 at 22:05
  • 2
    @pilchard -"*please avoid using gendered descriptors*" - I wasn't trying to be presumptious but please note the user's name is "Mr.Rendezvous". – But those new buttons though.. Feb 28 '23 at 22:07
  • But if you log the element itself after changing the property to `hello` and then changing type to `hidden` and back to `text` you'll see that it is changed in the HTML. Some strange alchemy – pilchard Feb 28 '23 at 22:09

3 Answers3

3

Admittedly a bit odd ... I found this w3c doc that might offer an explanation:

When an input element's type attribute changes state, the user agent must run the following steps:

  1. If the previous state of the element's type attribute put the value IDL attribute in the value mode, and the element's value is not the empty string, and the new state of the element's type attribute puts the value IDL attribute in either the default mode or the default/on mode, then set the element's value content attribute to the element's value.

  2. Otherwise, if the previous state of the element's type attribute put the value IDL attribute in any mode other than the value mode, and the new state of the element's type attribute puts the value IDL attribute in the value mode, then set the value of the element to the value of the value content attribute, if there is one, or the empty string otherwise, and then set the control's dirty value flag to false.

  3. Update the element's rendering and behavior to the new state's.

  4. Invoke the value sanitization algorithm, if one is defined for the type attribute's new state.

If I read it correctly, a type change will indeed fall back to the previous input value before type change if the new value is empty.

let inputHidden = document.getElementById('inputHidden');

console.log('1. hidden-text-hidden')

inputHidden.type = 'text';
inputHidden.value = '';
console.log('| text:', inputHidden.value, ' | att value:', inputHidden.getAttribute('value'), ' | type:', inputHidden.type);

inputHidden.type = 'hidden';
console.log('| hidden:', inputHidden.value, ' | att value:', inputHidden.getAttribute('value'), ' | type:', inputHidden.type);

console.log('\n 2. text-hidden-text')

let inputText = document.getElementById('inputText');

inputText.type = 'hidden';
inputText.value = 'hiddenVal';
console.log('| text:', inputText.value, ' | att value:', inputText.getAttribute('value'), ' | type:', inputText.type);

inputText.type = 'text';
inputText.value = '';
console.log('| text:', inputText.value, ' | att value:', inputText.getAttribute('value'), ' | type:', inputText.type);
<input id="inputHidden" type="hidden" value="hiddenAttValue">
<input id="inputText" type="text" value="textAttValue">
herrstrietzel
  • 11,541
  • 2
  • 12
  • 34
0

I think this is due to something quite special an empty string '' is actually nothing:

if ("")
  console.log("value is trufy")
else
  console.log("value is falsy")

this is props in JavaScript when changing implementations on display it calculates what the value in props really is something like this:

const lastValue = propValue || defaultValue
// lastValue === defaultValue because propValue = "" is falsy

if you use setAttribute the story will be different:

More info: https://gomakethings.com/the-difference-between-attributes-and-properties-in-vanilla-js/

var el   = document.getElementById('input');
el.type  = 'text';
el.setAttribute("value", '')
console.log('1', el.value);
el.type  = 'hidden';
console.log('2', el.value);
<input id="input" type="hidden" value="test">
Tachibana Shin
  • 2,605
  • 1
  • 5
  • 9
-1

Because you changes the value to an empty string '' before to change the type from «text» to «hidden» with javascript using el.value...

If you uses el.value to change the value of a «text» type input, the changes really don't act over DOM's node, after you changes the type to «hidden» the DOM will react as... if the new value is different to an empty value, sets the value attribute of the input to the new value, BUT if it's an empty value... it will keep the last value of the «value» attribute.

If you want a different behavior try el.setAttribute("value","") instead el.value=""

  • 2
    Trystan4861 - You've pretty much summed up what I described in my question but I don't see any explanation here. I don't "*want a different behaviour*" - I want to understand why the property `value` reverts when changing the property `type` - but only when it's an empty string. – But those new buttons though.. Feb 28 '23 at 22:21