ShadowTemplateMixin

Stamps a template into a component's Shadow DOM when instantiated

Overview

Purpose: Create a component's shadow root, and clone a template into it when it is first rendered.

This mixin forms a core part of the Elix render pipeline:

events → methods → setState → render

Expects the component to provide:

  • Internal symbols.template property that returns an HTMLTemplateElement used to populate the shadow tree of a new component.

Provides the component with:

  • Internal render implementation that creates and populates the shadow root the first time the component is rendered.
  • $ property that can be used to access elements in the shadow tree that have id attributes. See the $ property.

All Elix elements use ShadowTemplateMixin to populate their Shadow DOM subtree with template elements, so is included in the ReactiveElement base class.

Usage

import ShadowTemplateMixin from 'elix/src/ShadowTemplateMixin.js';
class MyElement extends ShadowTemplateMixin(HTMLElement) {}

ShadowTemplateMixin must be applied to your base class before any mixins or classes that want to render to elements in the Shadow DOM subtree. This is unusual for Elix mixins, which by design can usually be applied in any order.

Example

import ShadowTemplateMixin from 'elix/src/ShadowTemplateMixin.js';
import * as symbols from 'elix/src/symbols.js';

class GreetElement extends ShadowTemplate(HTMLElement) {

  connectedCallback() {
    this[symbols.render]();
  }

  get [symbols.template]() {
    const template = document.createElement('template');
    template.innerHTML = `Hello, <slot></slot>!`;
    return template;
  }

}

const element = new GreetElement();
element.textContent = 'world';      // User sees, "Hello, world!"

When the element above is instantiated, the constructor supplied by ShadowTemplateMixin finds the element's template and stamps it into a new shadow root.

Rendering

This mixin does its primary work in a component's symbols.render method. The first time that method is called, the mixin:

  1. Looks for a template property (see below).
  2. Attaches a new, open shadow root.
  3. Clones the template into the shadow root.

The template property

The ShadowTemplateMixin expects a component to define a property getter identified as symbols.template. If this property has not been defined, the mixin issues a console warning, but does not throw an exception.

The template property should return an HTML template (an HTMLTemplateElement). This HTMLTemplateElement can be defined by any means, including directly in JavaScript (as shown in the example above). You may also find it convenient to define a template with the html helper in the template module. Using that helper, the above example becomes:

import ShadowTemplateMixin from 'elix/src/ShadowTemplateMixin.js';
import * as symbols from 'elix/src/symbols.js';
import * as template from 'elix/src/template.js';

class GreetElement extends ShadowTemplate(HTMLElement) {
  get [symbols.template]() {
    return template.html`Hello, <slot></slot>!`;
  }
}

For better performance with components that dynamically construct a template, ShadowTemplateMixin caches a component's template.

API

Used by classes AlertDialog, ArrowDirectionButton, AutoCompleteComboBox, AutoCompleteInput, AutoSizeTextarea, Backdrop, Button, CalendarDay, CalendarDayNamesHeader, CalendarDays, CalendarMonth, CalendarMonthNavigator, CalendarMonthYearHeader, Carousel, CarouselSlideshow, CarouselWithThumbnails, CenteredStrip, CenteredStripHighlight, CenteredStripOpacity, ComboBox, CrossfadeStage, DateComboBox, DateInput, Dialog, Drawer, DropdownList, ExpandablePanel, ExpandableSection, Explorer, FilterComboBox, FilterListBox, HamburgerMenuButton, Input, ListBox, ListComboBox, ListExplorer, ListWithSearch, Menu, MenuButton, MenuItem, MenuSeparator, ModalBackdrop, Modes, Overlay, OverlayFrame, PageDot, Popup, PopupButton, PopupSource, ProgressSpinner, PullToRefresh, ReactiveElement, SeamlessButton, Slideshow, SlideshowWithPlayControls, SlidingPages, SlidingStage, TabButton, Tabs, TabStrip, Thumbnail, Toast, and WrappedStandardElement.

$ property

A convenient shortcut for looking up an element by ID in the component's Shadow DOM subtree.

Example: if component's template contains a shadow element <button id="foo">, you can use the reference this.$.foo to obtain the corresponding button in the component instance's shadow tree. The $ function is simply a shorthand for getElementById, so this.$.foo is the same as this.shadowRoot.getElementById('foo').

Type: object