In my following code a change of the value doesnt update the input value: Why?
class textfield extends HTMLElement {
get value()
{
return this.getAttribute("value");
}
set value(val)
{
this.setAttribute('value', val);
}
get readonly() {
return this.hasAttribute("readonly");
}
set readonly(val)
{
if (val)
{
this.setAttribute("readonly", '');
}
else
{
this.removeAttribute("readonly");
}
}
static get observedAttributes() {
return ['readonly', 'value'];
}
attributeChangedCallback(name, oldValue, newValue) {
console.log(name, newValue) ;
}
constructor()
{
super();
this.attachShadow({ "mode": "open" });
}
connectedCallback()
{
this.shadowRoot.innerHTML =
/*html*/`
<div>
<div>
Lable
</div>
<div>
<input id="vi-input" type="text" value="${this.getAttribute("value")}" ${ this.hasAttribute("readonly") ? "readonly" : "" } />
</div>
<div>
<span>Error</span>
</div>
</div>
`;
}
}
window.customElements.define("vi-textfield", textfield);
And in my index.html:
....
<vi-textfield id="myInput" value="2" validation="^\d{4}$" ></vi-textfield>
....
When I update it by JS, lets say by:
document.getElementById("myInput").value = 3;
there will be the given console.log of attributeChangedCallback but the value itself doesnt change....
Your input
doesn't update because they are 2 different elements.
set value(val) {
this.setAttribute('value', val);
}
sets the value
attribute on
<vi-textfield value="[val]">
not the value
attribute on
<input id="vi-input" type="text" value="${this.getAttribute("value")}"/>
which is another element in your elements shadowDOM
value="${this.getAttribute("value")}"
runs once, because connectedCallback()
runs once
If you want to set both, you can do:
set value(val) {
this.setAttribute('value', val);
this.shadowRoot.getElementById("vi-input").setAttribute("value", val);
}
If you want them in sync, you also need setAttribute code for when value
on the input changes.
PS.
set readonly(val) {
if (val) {
this.setAttribute("readonly", '');
} else {
this.removeAttribute("readonly");
}
}
can be written as:
set readonly(val) {
this.toggleAttribute("readonly", val);
}