I've created a custom select-component with LitElement:
import { LitElement, html } from 'lit-element';
class CustomSelect extends LitElement {
static get properties() {
return {
options: { type: Array },
selected: { type: String },
onChange: { type: Function }
};
}
constructor() {
super();
this.options = [];
}
render() {
return html`
<select @change="${this.onChange}">
${this.options.map(option => html`
<option value="${option.value}" ?selected=${this.selected === option.value}>${option.text}</option>
`)}
</select>
`;
}
createRenderRoot() {
return this;
}
}
customElements.define('custom-select', CustomSelect);
I pass in options
, selected
and onChange
as properties when I create the element. On the first render, everything works fine. All options are rendered and the selected value is reflected in the select. However, if I change selected
it doesn't seem to update the selected option. If I inspect the element with dev-tools, the selected
attribute is set correctly, but if I start querying the element for its value, it returns the wrong value.
One thing I tried is to add an id
attribute to the element via dev-tools after the select has been rendered. If I then change the selected
property on CustomSelect
, the id
attribute persists in the DOM, which says to me that the select is not re-rendered, which is what causing the issue, and why it's working on the first render.
I've tried setting the value
and selectedIndex
properties on the select-element, but it doesn't seem to affect anything in a meaningful way.
I've logged everywhere (beginning in render() and in the options-map) and all input values are correct.
It's I think, rendering time and selected property definition on onChange
functions timing conflict. So, better to assign a setTimeout
in onChange
then it's working properly. At my example at below link. I faced the same when I remove setTimeout
Also, you don't need to declare onChange
as function at properties.
Demo
static get properties() {
return {
options: { type: Array },
selected: { type: String }
};
}
constructor() {
super();
this.options = [{value:1, text:"ben"},{value:2, text:"sen"},{value:3, text:"oo"},{value:4, text:"biz"},{value:5, text:"siz"},{value:6, text:"onlar"}];
this.selected = 3
}
render() {
return html`
<select id="sel" @change="${this.onChange}">
${this.options.map(option => html`
<option value="${option.value}" ?selected=${this.selected === option.value}>${option.text}</option>
`)}
</select>
<button @click="${this.changeSelected}">Random chage selected option</button>
`;
}
onChange(x){
setTimeout(()=>{
this.selected = this.shadowRoot.querySelector('#sel').value
console.log('Selected -->', this.selected );
},300)
}
changeSelected(){
this.selected = (this.options[Math.floor(Math.random() * 6)].value)
console.log(this.selected)
}
Working example:
https://stackblitz.com/edit/litelement-testt-csgkmc
Fixed using the repeat directive.
import { repeat } from 'lit-html/directives/repeat';
${repeat(this.sortedRows, e => e, row => html`
<tr>
${row.map((cell, index) => html`
<td>${this.onRenderCell(cell, index, row)}</td>
`)}
</tr>
`)}
https://github.com/Polymer/lit-element/issues/805#issuecomment-530461555
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With