1

The source code:

import { LitElement, html, css } from '../vendor/lit-2.4.0/lit-all.min.js';

export class SearchInput extends LitElement {
    static get properties() {
        return {
            src: { type: String },
            items: { type: Array }
        }
    };

    static styles = css`
    `;

    constructor() {
        super();
        this.items = [
            { text: 'Hola' },
            { text: 'mundo!' }
        ];
        this.selectedItem = null;
        this.text = 'foo';
    }

    selectItem(item) {
        this.selectedItem = item;
        this.text = this.selectedItem.text;
    }

    render() {
        return html`
            <div class="control">
                <input class="input" type="text" value="${this.text}">
                <ul class="result-list">
                    ${this.items.map((item) => html`<li @click="${this.selectItem(item)}">${item.text}</li>`)}
                </ul>
            </div>
        `;
    }
}
customElements.define('search-input', SearchInput);

The text input (input type="text") value is not updating after changing property (this.text) using an event (this.selectItem) with LitElement library.

I tried it in browser but there is no error in browser console. I expect that input value update after changing property with the event.

Pedro Urday
  • 93
  • 2
  • 5

1 Answers1

1

Thanks for the question! There are a few minor issues resulting in the value not updating.

One issue is that this.text is not a reactive property, so changing it isn't scheduling a re-render. Fix is to add text to the static properties.

The second issue is that your event listener click handler is the result of calling this.selectItems(item) and not a function, fixed with: @click=${() => this.selectItems(item)}.

Bonus: You may want to change the value attribute expression to a property expression using the live directive, .value="${live(this.text)}". I suggested this because the native input browser element always updates its contents if you update the value property, but only updates before a user has interacted with it when updating the value attribute. And the live directive is useful to tell Lit to dirty check the live DOM value in the input element.

Your code with the minor fixes: https://lit.dev/playground/#gist=a23dfbcdfbfcfb7de28b1f7255aaa8ee

or running in StackOverflow:

<script type="module">
import { LitElement, html, live } from 'https://cdn.jsdelivr.net/gh/lit/dist@2/all/lit-all.min.js';

class SearchInput extends LitElement {
  static get properties() {
    return {
      src: { type: String },
      items: { type: Array },
      text: { type: String }, // <- Added this to make `this.text` a reactive property.
    }
  };

  constructor() {
    super();
    this.items = [
      { text: 'Hola' },
      { text: 'mundo!' },
      { text: 'click these' },
    ];
    this.selectedItem = null;
    this.text = 'foo';
  }

  selectItem(item) {
    this.selectedItem = item;
    this.text = this.selectedItem.text;
  }

  render() {
    return html`
      <div class="control">
        <!-- live directive is needed because user can edit the value of the input.
              This tells Lit to dirty check against the live DOM value. -->
        <input class="input" type="text" .value="${live(this.text)}">
        <ul class="result-list">
            <!-- Click event is a function -->
            ${this.items.map((item) =>
              html`<li @click="${() => this.selectItem(item)}">${item.text}</li>`)}
        </ul>
      </div>
      `;
  }
}
customElements.define('search-input', SearchInput);
</script>
<search-input></search-input>
YouCodeThings
  • 590
  • 3
  • 13