DelegateItemsMixin

Treats the items inside a shadow element as the component's own items

Overview

Purpose: Lets the items of a shadow element serve as the items of the component itself.

This mixin works in the middle of the Elix render pipeline:

events → methods ➞ setState → render DOM → post-render

Expects the component to provide:

  • [internal.state].selectedIndex property indicating the index of the currently selected item. This is usually provided by SingleSelectAPIMixin.
  • internal.itemsDelegate property that returns a reference to the shadow element to which the component is delegating management of the selection state. This should be a list-like element (e.g., a ListBox or variant thereof) inside the component's shadow root.

Provides the component with:

  • [internal.state].items member and public items property representing the items that can be selected. These match the semantics of the items property provided by ContentItemsMixin.
  • Synchronization between the selectedIndex of the component itself and the inner shadow element to which the component has delegated its items.

Usage

The following component includes a ListBox as a shadow element. The component puts its own light DOM children inside that ListBox via its default slot. The component that delegates its own items property to that ListBox by setting a internal.selectionDelegate property pointing at the ListBox.

import "elix/define/ListBox.js";
import { html } from "elix/src/template.js";
import * as internal from "elix/src/internal.js";
import DelegateItemsMixin from "elix/src/base/DelegateItemsMixin.js";
import ReactiveElement from "elix/define/ReactiveElement.js";
import SingleSelectAPIMixin from "elix/src/base/SingleSelectAPIMixin.js";

const Base = DelegateItemsMixin(SingleSelectAPIMixin(ReactiveElement));

class MyElement extends Base {
  get [internal.itemsDelegate]() {
    return this[internal.ids].innerList;
  }

  get [internal.template]() {
    return html`
      <elix-list-box id="innerList">
        <slot></slot>
      </elix-list-box>
      <div>Other shadow elements</div>
    `;
  }
}

With this arrangement, if the user interacts with the inner ListBox to select an item, the selection state of the ListBox will be mirrored on the outer MyElement component. This makes the selection state of the inner ListBox visible to the page. In the other direction, if the selection state of the outer component is programmatically manipulated — by setting the selectedIndex property or calling a selection method — that selection will be passed on to the inner ListBox.

Components like ListComboBox and ListWithSearch use DelegateItemsMixin in this way to treat the selection state of an inner ListBox (or variant) as their own selection state.