I have following code:
export class ViTextfield extends LitElement
{
static get properties() {
return {
value: { type: String },
}
onChange(e) { console.log(e.target.value) }
render()
{
return html`
<div>
<div>
<input id="vi-input"
type="text"
value="${this.value}"
@change=${this.onChange} />
</div>
</div>
`
}
So everything is working fine for itself. Now the developer who is using my component should be able to set the value thorugh the property e.g.
document.getElementById('myComponent').value = 1;
Now that brings 2 problems: 1) the value itself is not updated and 2) the onchange is not fired
Problem 1 I fixed with changing
value="${this.value}"
to
.value="${this.value}"
even I dont know why it is working (found this hack online).
But still the onChange is not firing...
The code doesn't work as you expect it to due to a couple of things:
value
not work when .value
does?lit-html uses the dot here to distinguish between assigning the value attribute or the property (value
assigns the attribute and .value
the property)
The easiest way of thinking about this is that attributes are those set on the HTML itself and properties are set to the Javascript object that represents that node.
Now, this is important in this case because the value property of an input element is only set from the attribute the when it's first rendered, if you want to change it later on you must set the property, not the attribute. Source
This is because the change event is fired from the input only when the input's value changed due to some user input. Source
If you want to have some sort of side effect that gets fired not only when the user interacts when the input, but also when the property is modified in code, you probably want to use a setter. In your case that would look like this:
export class ViTextfield extends LitElement {
static get properties() {
return {
value: {
type: String
},
}
}
set value(value) {
const oldValue = this.value;
// do some side effect here
// set a pseudo-private property that will contain the actual value
this._value = value;
// call LitElement's requestUpdate so that a rerender is done if needed
this.requestUpdate('value', oldValue);
}
get value() {
// return the pseudo-private so that when vitextfield.value is accessed the correct value is returned
return this._value;
}
onChange(e) {
// update the property so that it keeps up with the input's current value
this.value = e.target.value;
}
render() {
return html `
<div>
<div>
<input id="vi-input"
type="text"
value="${this.value}"
@change=${this.onChange} />
</div>
</div>
`
}
}
For more info check this part of the LitElement guide