Blog Logo

28-Mar-2024 ~ 2 min read

Communication Between Sibling Lit Elements Using Native JavaScript Events


In a Lit application, it’s common to have sibling components that need to communicate with each other. While Lit provides powerful tools for managing component state and properties, sometimes you may need a way for sibling components to exchange information or trigger actions without directly passing data through properties or attributes. In this guide, we’ll explore how to achieve communication between sibling Lit elements using native JavaScript events.

Table of Contents

1. Introduction

In a Lit application, components are designed to be reusable and encapsulated, which means they should ideally be independent of each other. However, there are scenarios where sibling components need to communicate or synchronize their behavior. Using native JavaScript events allows components to remain decoupled while enabling communication between them.

2. Creating the Sender Element (sender-select.js)

// sender-select.js
import {
  LitElement,
  css,
  html,
} from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js';

class SenderSelect extends LitElement {
  static styles = css`
    :host {
      display: block;
    }
  `;

  static properties = {
    options: { type: Array },
    selectedOption: { type: String },
  };

  constructor() {
    super();
    this.options = [];
    this.selectedOption = '';
  }

  render() {
    return html`
      <select @change=${this.handleChange}>
        ${this.options.map(
          option => html`<option value=${option}>${option}</option>`
        )}
      </select>
    `;
  }

  handleChange(event) {
    this.selectedOption = event.target.value;
    this.dispatchEvent(
      new CustomEvent('sender-select-changed', {
        detail: {
          selectedOption: this.selectedOption,
        },
      })
    );
  }
}

customElements.define('sender-select', SenderSelect);

3. Creating the Receiver Element (receiver-paragraph.js)

// receiver-paragraph.js
import {
  LitElement,
  css,
  html,
} from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js';

class ReceiverParagraph extends LitElement {
  static properties = {
    jobid: { type: String },
  };

  render() {
    return html`<div>Long Job with Job ID: ${this.jobid}</div>`;
  }
}

customElements.define('receiver-paragraph', ReceiverParagraph);

4. Testing (index.html)

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Lit Sibling Communication Using Custom Events Example</title>

    <script type="module" src="./sender-select.js"></script>
    <script type="module" src="./receiver-paragraph.js"></script>
  </head>

  <body>
    <sender-select options='["job1", "job2", "job3"]'></sender-select>
    <receiver-paragraph jobid="..."></receiver-paragraph>

    <script>
      const senderSelectElement = document.querySelector('sender-select');
      const receiverParagraphElement =
        document.querySelector('receiver-paragraph');
      senderSelectElement.addEventListener('sender-select-changed', event => {
        receiverParagraphElement.jobid = event.detail.selectedOption; // Update the jobid attribute of receiver-paragraph
      });
    </script>
  </body>
</html>

5. Conclusion

Using native JavaScript events for communication between sibling Lit elements provides a flexible and decoupled approach to exchange information and trigger actions. By dispatching and listening for custom events, components can remain independent while still enabling interaction and coordination within the application. However, be mindful of potential performance implications when relying heavily on event-based communication, especially in large applications with many components.