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 → renderupdate DOM

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 symbols.render() method 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.

Usage

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

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 looks for a template property (see below).
  • If the ShadyCSS polyfill is loaded, the mixin processes the template so that it can be used with ShadyCSS.
  • The mixin attaches a new, open shadow root.
  • The mixin clones the prepared template into the shadow root.
  • If the ShadyCSS polyfill is loaded, in the component's connectedCallback, the mixin invokes ShadyCSS to apply styles to the new component instance.

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>!`;
  }
}

Template caching

For better performance, ShadowTemplateMixin caches a component's processed template.

The mixin reads the [symbols.template] property once, in the constructor. After preparing the template for use with ShadyCSS, the processed template is cached.

Subsequent component instantiations will use the cached template directly.

API

Used by classes AlertDialog, ArrowDirectionButton, AutoCompleteInput, AutoSizeTextarea, Backdrop, Button, CalendarDay, CalendarDayNamesHeader, CalendarMonth, CalendarMonthDays, CalendarMonthYearHeader, CalendarWeek, Carousel, CarouselSlideshow, CarouselWithThumbnails, CenteredStrip, CenteredStripHighlight, CenteredStripOpacity, ComboBox, CrossfadeStage, Dialog, Drawer, DropdownList, ExpandablePanel, ExpandableSection, Explorer, HamburgerMenuButton, ListBox, ListComboBox, ListExplorer, 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