英文:
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 field 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.
英文:
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.
答案1
得分: 5
根据HTML规范,list
content属性确实被指定为包含相应datalist
元素的ID:
> list
属性用于标识一个列出预定义选项的元素,建议给用户使用。
> 如果存在,其值必须是同一树中datalist
元素的ID。
然而,input
元素的list
IDL属性(如DOM接口中规定的)是只读的,返回的是实际的HTMLDataListElement
而不是其ID:
> interface HTMLInputElement : HTMLElement {
> // ...
> readonly attribute HTMLDataListElement? list;
> // ...
> }
然而,您可以使用setAttribute()
函数来操作list
content属性,并以这种方式在input
元素上设置datalist
的ID:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
document.querySelector('#input').setAttribute('list', 'values');
<!-- language: lang-html -->
<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>
<!-- end snippet -->
英文:
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:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
document.querySelector('#input').setAttribute('list', 'values');
<!-- language: lang-html -->
<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>
<!-- end snippet -->
答案2
得分: 1
HTML中的属性<tag attribute="value">
与Element
的属性是有区别的。
从HTML中检索到的属性存储在NamedNodeMap attributes;
中,并可通过setAttribute
和getAttribute
进行控制。
DOM元素的属性(继承自Element
的属性)不需要具有相同的值(即使它们具有相同的名称),它们的值是从存储在attributes
中的Attr
派生的。
如果您查看此示例,您会发现根据您操作和检索的对象,行为会有所不同:
document.getElementById('test1').setAttribute('value','html-value')
document.getElementById('test2').setAttribute('value','html-value')
document.getElementById('test2').value = 'js-value'
document.getElementById('test3').value = 'js-value'
console.log(document.getElementById('test3').getAttribute('value'))
因此,对于list
,DOM元素的属性是基于为具有名称list的Node
属性设置的内容创建的。
DOM元素的list
属性可能设置为只读,其中包含一个元素列表,因为该列表无法映射回一个ID。
英文:
There is a difference between an attribute in HTML <tag attribute="value">
, and an attribute of that an Element
.
The attributes retrieved from the HTML are stored in NamedNodeMap attributes;
and can be controlled using e.g. setAttribute
and getAttribute
.
The attribute an DOM Elements (that inherit from Element
) do not need (even if they have the same name) to have the same value, their value is derived from the Attr
stored in attributes
.
If you take a look at this example, you can see that there is a difference in behavior depending on which one you manipulate and retrieve:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
document.getElementById('test1').setAttribute('value','html-value')
document.getElementById('test2').setAttribute('value','html-value')
document.getElementById('test2').value = 'js-value'
document.getElementById('test3').value = 'js-value'
console.log(document.getElementById('test3').getAttribute('value'))
<!-- language: lang-css -->
[value="html-value"] {
color: red;
}
[value="js-value"] {
color: green;
}
<!-- language: lang-html -->
Test1:
<input id="test1">
Test2:
<input id="test2">
Test3:
<input id="test3">
<!-- end snippet -->
So for list
the attribute of the DOM Element is created based on what is set for the Attribute Node
with the name list (which is an ID).
The list
attribute of the DOM Element is probably set to readonly which contains a list of elements, because that list could not be mapped back to an ID.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论