Search code examples
javascripthtmltypescriptdenots-node

Why does the HTMLInputElement's `list` field only have a getter, and no setter?


I'm creating an HTMLInputElement in Typescript, which I intend to use as a "slider" by setting the input element's type field to "range".

According to MDN Web Docs, I can make this slider fancier by creating an instance of an HTMLDatalistElement, giving the datalist an id, and referencing the datalist's id via the slider's list field. This will not only give my slider some tick marks to denote where the slider cursor is currently located, but I can then set the datalist's HTMLOptionElement's label field to introduce labelled tick marks.

Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range#adding_labels

However, Deno/TS-Node complains with this error:

error: TS2540 [ERROR]: Cannot assign to 'list' because it is a read-only property.
      inputElement.list = datalistId;

and Google Chrome complains with this error:

Uncaught TypeError: Cannot set property list of #<HTMLInputElement> which has only a getter

Since the MDN Web Docs clearly show that this fields is meant to be used, I attempted to silence the Deno/TS-Node error by ignoring it via:

// @ts-ignore

This solution did not work, and resulted in the above Google Chrome runtime error.

I don't understand why this field is allowed to be set when constructing an HTMLInputElement via an .html file, but you aren't allowed to use it when creating an instance of an HTMLInputElement dynamically via Javascript/Typescript. Being able to dynamically set a slider's tick mark labels would be very nice.


Solution

  • According to the HTML specification, the list content attribute is indeed specified to contain the ID of a corresponding datalist element:

    The list attribute is used to identify an element that lists predefined options suggested to the user.
    If present, its value must be the ID of a datalist element in the same tree.

    However, the input element's list IDL attribute (as specified in the DOM interface) is read-only, and returns the actual HTMLDataListElement instead of its ID:

    interface HTMLInputElement : HTMLElement {
      // ...
      readonly attribute HTMLDataListElement? list;
      // ...
    }
    

    You can, however, manipulate the list content attribute using the setAttribute() function, and set the datalist ID on the input element that way:

    document.querySelector('#input').setAttribute('list', 'values');
    <input id="input" type="range">
    <datalist id="values">
      <option value="0" label="0"></option>
      <option value="50" label="50"></option>
      <option value="100" label="100"></option>
    </datalist>