skip to Main Content

Let’s have, say, an element with the text content of Clark, Theodore S.. Note the double white spaces after the "Theodore". Say you have this element be an HTML option, like this: <option>Clark, Theodore S.</option>. If you try to extract its text content, you would correctly get the result Clark, Theodore S.. However, if you try to get the option’s value property, you get Clark, Theodore S..

As per MDN’s docs, white spaces are often times ignored when formatting the DOM. However, wouldn’t it be logical to have the textContent property return the trimmed value and the value property return the exact value? As far as I know, when you get the value of an input element no trimming is performed, so why is it done here?

Why is the value property modified in any way when it is expected that it would most accurately reflect the actual value set? Is this a bug in JavaScript or is it explicitly intended?

2

Answers


  1. The textContent of a HTMLOptionElement is not its value per se. Its value is/should be defined by its value attribute. If no value attribute is present, the text content is taken and apparently that content is cleaned up.

    from the MDN link above:

    [Option.value] A string representing the value of the HTMLOptionElement, i.e. the value attribute of the equivalent . If this is not specified, the value of text is used as the value, e.g. for the associated element’s value when the form is submitted to the server.

    If you need the exact value without a value attribute, innerText or textContent or innerHTML may be the alternative. Here’s a comparison:

    const opt = new Option(`hello     <i>world</i>`)
    console.log(`*opt*nvalue: ${
      opt.value}ntextContent: ${
      opt.textContent}ninnerText: ${
      opt.innerText}ninnerHTML ${
      opt.innerHTML}`);
      
    const opt2 = new Option(`hello     <i>world</i>`, `hello     <i>world</i>`);
    console.log(`*opt2*nvalue: ${
      opt2.value}ntextContent: ${
      opt2.textContent}ninnerText: ${
      opt2.innerText}ninnerHTML ${
      opt2.innerHTML}`);
    .as-console-wrapper {
        max-height: 100% !important;
    }
    Login or Signup to reply.
  2. It’s because in the absence of a value attribute, the .text value is used as the <option>‘s value.
    From the specs for HTMLOptionElement.prototype.text

    The text IDL attribute, on getting, must return the result of stripping and collapsing ASCII whitespace from the concatenation of data of all the Text node descendants of the option element, in tree order, excluding any that are descendants of descendants of the option element that are themselves script or SVG script elements.

    Thanks to this, we can write stuff like the following and still have the value foo bar being sent to the server as is likely expected.

    const el = document.querySelector("option");
    console.log(el.text, el.text === el.value);
    console.log(el.textContent);
    <select>
      <option>
        foo
        bar
        <script>
        // Something
        </script>
      </option>
    </select>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search