ContentItemsMixin

Treats an element's content nodes as list items

Overview

Purpose: lets a list-like component obtain its list items from its DOM content. It expects the component to identify its HTML "contents", and then impose some restrictions on those contents to determine which of those HTML elements are actually interesting to use as the items in the list.

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

events → methods → setStaterender DOM → post-render

Expects the component to provide:

  • [internal.state].content member containing a flattened array of Node elements. You can use SlotContentMixin for this purpose.

Provides the component with:

  • [internal.state].items member containing the content elements that should be treated as list items. See Obtaining items from content below.

Usage

import ContentItemsMixin from "elix/src/base/ContentItemsMixin.js";
class MyElement extends ContentItemsMixin(HTMLElement) {}

Items differ from raw element contents in several ways:

  • They are often referenced via index.
  • They may have a selection state.
  • It's common to do work to initialize the appearance or state of a new item.
  • Text nodes (which are often whitespace) are ignored.
  • Invisible child elements are filtered out and not counted as items. Instances of invisible Node subclasses such as Comment and ProcessingInstruction are filtered out, as are invisible auxiliary elements include link, script, style, and template elements. This filtering ensures that those auxiliary elements can be used in markup inside of a list without being treated as list items.

This mixin is designed to address the Gold Standard checklist criteria for Child Independence (Can you use the component with a wide range of child element types?) and Auxiliary Content (Does the component permit the use of child elements that perform auxiliary functions?). To meet those criteria, it is better for a component to filter out what it doesn't want using ContentItemsMixin than to exclusively filter in only a specific type of element (using, say, querySelectorAll).

Example

<my-element>
  <style>
    div {
      color: gray;
    }
  </style>
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</my-element>

If this element uses ContentItemsMixin, its items property will return the three div elements, and filter out the whitespace text nodes and the invisible style element.

Obtaining items from content

ContentItemsMixin expects a component to define a state member [internal.state].content containing the raw set of HTML elements the component contains. How a component interprets "contains" can vary, but a common definition would be the component's light DOM children. In that common case, SlotContentMixin can be used to define [internal.state].content as the light DOM children assigned to the component's default slot.

Other definitions of content are possible. Your component could, for example, define [internal.state].content to only extract nodes assigned to a particular named slot, or the children of a node in the component's shadow tree, or a set of nodes not actually in the DOM.

ContentItemsMixin manages a state member called [internal.state].items that filters the results of [internal.state].content. This is an array of items designed for use with SingleSelectAPIMixin and its companion mixins. ContentItemsMixin uses the helper function content.substantiveElements to subtract out any nodes in [internal.state].content that would not normally be visible to the user.

Rendering updates to items

List-like components often need to update their light DOM content too, e.g., to add attributes or classes to the nodes for list items. A component can render state changes to its items in its internal.render method. See SingleSelectAPIMixin for an example.

API

Used by class SlotItemsMixin.