or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

data-binding.mdelement-creation.mdgesture-system.mdindex.mdlegacy-support.mdmixins.mdproperty-system.mdutilities.md
tile.json

data-binding.mddocs/

Data Binding & Templates

Template system with data binding, conditional rendering, list iteration, and event handling capabilities.

Capabilities

Data Binding Syntax

Polymer's template binding syntax for connecting element properties to template content.

/**
 * One-way binding: [[property]] - data flows from element to template
 * Two-way binding: {{property}} - data flows both ways  
 * Attribute binding: attribute="[[property]]" or attribute$="[[property]]"
 * Event binding: on-event="handler"
 */

Usage Examples:

import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';

class BindingExample extends PolymerElement {
  static get is() { return 'binding-example'; }
  
  static get template() {
    return html`
      <!-- One-way text binding -->
      <div>Hello [[name]]!</div>
      
      <!-- Two-way input binding -->
      <input value="{{inputValue::input}}" placeholder="Type here">
      <div>You typed: [[inputValue]]</div>
      
      <!-- Attribute binding -->
      <img src="[[imageUrl]]" alt="[[imageAlt]]">
      <div class$="[[computeClass(active)]]">Status</div>
      
      <!-- Boolean attribute binding -->
      <button disabled$="[[!canSubmit]]">Submit</button>
      
      <!-- Event binding -->
      <button on-click="handleClick">Click me</button>
      <input on-keydown="handleKeydown">
      
      <!-- Property binding to child elements -->
      <child-element data="[[complexData]]" on-data-changed="handleDataChange"></child-element>
      
      <!-- Computed binding -->
      <div>Total: [[computeTotal(items.*)]]</div>
    `;
  }
  
  static get properties() {
    return {
      name: String,
      inputValue: String,
      imageUrl: String,
      imageAlt: String,
      active: Boolean,
      canSubmit: Boolean,
      complexData: Object,
      items: Array
    };
  }
  
  computeClass(active) {
    return active ? 'active' : 'inactive';
  }
  
  computeTotal(changeRecord) {
    return changeRecord.base.reduce((sum, item) => sum + item.value, 0);
  }
  
  handleClick(e) {
    console.log('Button clicked:', e);
  }
  
  handleKeydown(e) {
    if (e.key === 'Enter') {
      console.log('Enter pressed');
    }
  }
  
  handleDataChange(e) {
    console.log('Child data changed:', e.detail.value);
  }
}

Conditional Rendering (dom-if)

Element for conditionally rendering template content based on boolean conditions.

/**
 * Conditionally stamps template content based on if property
 */
class DomIf extends PolymerElement {
  /** Boolean condition that controls template rendering */
  if: boolean;
  
  /** Whether to destroy and recreate content when condition changes */
  restamp: boolean;
}

Usage Examples:

class ConditionalExample extends PolymerElement {
  static get is() { return 'conditional-example'; }
  
  static get template() {
    return html`
      <button on-click="toggleShow">Toggle Content</button>
      
      <!-- Basic conditional -->
      <template is="dom-if" if="[[showContent]]">
        <div>This content is conditionally shown</div>
      </template>
      
      <!-- Conditional with restamp -->
      <template is="dom-if" if="[[showForm]]" restamp>
        <form>
          <input type="text" placeholder="This form is recreated each time">
          <button type="submit">Submit</button>
        </form>
      </template>
      
      <!-- Nested conditionals -->
      <template is="dom-if" if="[[user]]">
        <div class="user-section">
          <h3>Welcome [[user.name]]!</h3>
          <template is="dom-if" if="[[user.isAdmin]]">
            <div class="admin-panel">Admin Controls</div>
          </template>
        </div>
      </template>
    `;
  }
  
  static get properties() {
    return {
      showContent: Boolean,
      showForm: Boolean,
      user: Object
    };
  }
  
  toggleShow() {
    this.showContent = !this.showContent;
  }
}

List Rendering (dom-repeat)

Element for rendering lists of data with templating and filtering capabilities.

/**
 * Renders a template for each item in an array
 */
class DomRepeat extends PolymerElement {
  /** Array of items to render */
  items: any[];
  
  /** Name for each item in template scope (default: 'item') */
  as: string;
  
  /** Name for item index in template scope (default: 'index') */
  indexAs: string;
  
  /** Sort function for items */
  sort: (a: any, b: any) => number;
  
  /** Filter function for items */
  filter: (item: any) => boolean;
  
  /** Space-separated list of properties to observe on items */
  observe: string;
  
  /** Delay in microseconds before rendering changes */
  delay: number;
  
  /** Number of currently rendered items */
  renderedItemCount: number;
  
  /** Force re-render of all items */
  render(): void;
  
  /** Get the item associated with a rendered element */
  itemForElement(el: Element): any;
  
  /** Get the index of item associated with a rendered element */
  indexForElement(el: Element): number;
}

Usage Examples:

class ListExample extends PolymerElement {
  static get is() { return 'list-example'; }
  
  static get template() {
    return html`
      <!-- Basic list -->
      <template is="dom-repeat" items="[[users]]">
        <div class="user-item">
          <span>[[item.name]]</span> - <span>[[item.email]]</span>
        </div>
      </template>
      
      <!-- List with custom item name -->
      <template is="dom-repeat" items="[[products]]" as="product">
        <div class="product-card">
          <h3>[[product.title]]</h3>
          <p>$[[product.price]]</p>
        </div>
      </template>
      
      <!-- List with index -->
      <template is="dom-repeat" items="[[items]]" as="item" index-as="i">
        <div>[[i]]: [[item]]</div>
      </template>
      
      <!-- Filtered and sorted list -->
      <template is="dom-repeat" items="[[allUsers]]" filter="isActiveUser" sort="sortByName" observe="name active">
        <div class="active-user">[[item.name]] ([[index]])</div>
      </template>
      
      <!-- Nested lists -->
      <template is="dom-repeat" items="[[categories]]" as="category">
        <div class="category">
          <h3>[[category.name]]</h3>
          <template is="dom-repeat" items="[[category.items]]" as="categoryItem">
            <div class="category-item">[[categoryItem.name]]</div>
          </template>
        </div>
      </template>
    `;
  }
  
  static get properties() {
    return {
      users: Array,
      products: Array,
      items: Array,
      allUsers: Array,
      categories: Array
    };
  }
  
  isActiveUser(user) {
    return user.active;
  }
  
  sortByName(a, b) {
    return a.name.localeCompare(b.name);
  }
}

Data Binding Element (dom-bind)

Element that provides data binding capabilities without creating a custom element.

/**
 * Provides data binding in templates without defining a custom element
 */
class DomBind extends PolymerElement {
  /** Notify path changes up the binding tree */
  notifyPath(path: string, value: any): void;
  
  /** Set value at a path and notify */
  set(path: string, value: any): void;
  
  /** Get value at a path */
  get(path: string): any;
}

Usage Examples:

<!-- In HTML, not inside a custom element -->
<dom-bind>
  <template>
    <h1>[[title]]</h1>
    <input value="{{message::input}}">
    <p>You typed: [[message]]</p>
    
    <template is="dom-repeat" items="[[items]]">
      <div>[[item]]</div>
    </template>
  </template>
</dom-bind>

<script>
  const domBind = document.querySelector('dom-bind');
  domBind.title = 'My App';
  domBind.message = 'Hello';
  domBind.items = ['One', 'Two', 'Three'];
</script>

Array Selection (array-selector)

Utility for managing selection state in arrays.

/**
 * Mixin for managing selection state in arrays
 */
interface ArraySelectorMixin {
  /** Array of items to manage selection for */
  items: any[];
  
  /** Whether multiple selections are allowed */
  multi: boolean;
  
  /** Currently selected item (single mode) */
  selected: any;
  
  /** Array of selected items (multi mode) */
  selectedItems: any[];
  
  /** Select an item */
  select(item: any): void;
  
  /** Deselect an item */
  deselect(item: any): void;
  
  /** Check if item is selected */
  isSelected(item: any): boolean;
  
  /** Clear all selections */
  clearSelection(): void;
}

/**
 * Standalone element for array selection
 */
class ArraySelector extends PolymerElement {
  items: any[];
  multi: boolean;
  selected: any;
  selectedItems: any[];
  
  select(item: any): void;
  deselect(item: any): void;
  isSelected(item: any): boolean;
  clearSelection(): void;
}

Usage Examples:

class SelectionExample extends PolymerElement {
  static get is() { return 'selection-example'; }
  
  static get template() {
    return html`
      <!-- Array selector element -->
      <array-selector id="selector" items="[[items]]" selected="{{selected}}" multi></array-selector>
      
      <!-- Display items with selection state -->
      <template is="dom-repeat" items="[[items]]">
        <div class$="[[computeItemClass(item, selected.*)]]" on-click="selectItem">
          [[item.name]]
        </div>
      </template>
      
      <!-- Selected items display -->
      <div>Selected: [[selected.length]] items</div>
    `;
  }
  
  static get properties() {
    return {
      items: Array,
      selected: Array
    };
  }
  
  selectItem(e) {
    const item = e.model.item;
    this.$.selector.select(item);
  }
  
  computeItemClass(item, selectedChangeRecord) {
    const isSelected = this.$.selector.isSelected(item);
    return isSelected ? 'selected' : '';
  }
}

DOM Module Registration (dom-module)

Element for registering templates and styles by ID for use in Polymer elements.

/**
 * Element for registering templates and styles by ID
 */
class DomModule extends PolymerElement {
  /** Module ID for registration */
  id: string;
  
  /** Registered template element */
  template: HTMLTemplateElement;
  
  /** Array of style elements */
  styles: HTMLStyleElement[];
  
  /** Static method to import a module by ID */
  static import(id: string, selector?: string): HTMLElement | null;
  
  /** Register this module */
  register(id?: string): void;
}

Usage Examples:

<!-- Define a template module -->
<dom-module id="my-element">
  <template>
    <style>
      :host {
        display: block;
        color: var(--my-element-color, blue);
      }
    </style>
    <div>[[message]]</div>
  </template>
</dom-module>

<script>
  // Use the template in an element
  class MyElement extends PolymerElement {
    static get is() { return 'my-element'; }
    // Template is automatically found from dom-module
  }
  customElements.define(MyElement.is, MyElement);
</script>

Custom Style Definition (custom-style)

Element for defining global styles that can use ShadyCSS features.

/**
 * Element for defining document-level styles with ShadyCSS support
 */
class CustomStyle extends HTMLElement {
  /** Style modules to include */
  include: string;
  
  /** Update the custom style */
  updateStyles(): void;
  
  /** Get style information */
  getStyle(): CSSStyleSheet;
}

Usage Examples:

<!-- Define global custom properties and styles -->
<custom-style>
  <style>
    html {
      --primary-color: #1976d2;
      --secondary-color: #388e3c;
      --app-background: #fafafa;
    }
    
    body {
      background-color: var(--app-background);
      margin: 0;
      font-family: 'Roboto', sans-serif;
    }
  </style>
</custom-style>

<!-- Include styles from dom-modules -->
<custom-style include="shared-styles app-theme">
  <style>
    /* Additional styles here */
    .app-header {
      background-color: var(--primary-color);
    }
  </style>
</custom-style>

Types

interface TemplateInfo {
  dynamicFns?: {[property: string]: boolean};
}

interface NodeInfo {
  id?: string;
  events?: Array<{name: string, value: string}>;
  bindings?: Array<Binding>;
}

interface Binding {
  kind: 'property' | 'attribute' | 'text';
  target: string;
  parts: Array<BindingPart>;
}

interface BindingPart {
  mode: '{' | '[';
  source: string;
  signature?: {
    methodName: string;
    static: boolean;
    dynamicFn: boolean;
  };
}