Reputation: 15138
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....
Upvotes: 0
Views: 1693
Reputation: 21183
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);
}
Upvotes: 3
Reputation: 4975
I guess you are setting the value, but not doing anything after that, at least not to the input field.. Your element vi-textfield
actually is updated if you have a look at your elements tab using your browser's developer tools. You might be able to rebuild your html for example after setting the value by calling
this.connectedCallback();
To make sure the input field contains the updated value as well.
Or you need to find a way to select and update the input field separately. Or just recall the connectedCallback()
method like I mentioned.
Or you could add some kind of MutationObserver to your class (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver), but I don't think this should work out of the box what you might have thought: while updating the value of the host, update the shadow elements.
Upvotes: 0