admin管理员组

文章数量:1302374

I've created a custom select-ponent 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.

I've created a custom select-ponent 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.

Share asked Apr 25, 2019 at 21:45 CaptainBarefootCaptainBarefoot 811 silver badge3 bronze badges 2
  • I'd like to add that in the real application, the select is being rendered in a td in a table. When the select is changed, I fire a state change through Redux that changes the state of some values in the table row, which causes a render of all the rows. Everything else renders correctly. Could it be that since the select is causing the change, its internal state gets stuck somehow? – CaptainBarefoot Commented Apr 26, 2019 at 13:28
  • Adding some extra information: 1. The table is initialized like this. It's sorted on "Status". The selected option is reflected correctly. 2. I change the option like this. This updates the state, and in turn rerenders the rows. The other columns updates correctly, but the select is displaying the incorrect value, even though the option has the correct value selected. The old row is sorted away since we sort on that same column, but it's still displaying the state of that old select on the new row. – CaptainBarefoot Commented Apr 27, 2019 at 13:10
Add a ment  | 

2 Answers 2

Reset to default 4

Working example:

https://stackblitz./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./Polymer/lit-element/issues/805#issuement-530461555

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)
} 

本文标签: javascriptCustom litelement select not rerendering correctlyStack Overflow