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

property-system.mddocs/

Property System

Declarative property configuration with automatic attribute synchronization, change notification, computed properties, and property observation.

Capabilities

Property Declaration

Configure element properties with automatic attribute synchronization and change observation.

/**
 * Property configuration object that defines element properties
 */
interface PropertyDeclarations {
  [property: string]: PropertyType | PropertyDeclaration;
}

/**
 * Detailed property configuration
 */
interface PropertyDeclaration {
  /** Type constructor for attribute deserialization */
  type?: PropertyType;
  
  /** Default value or function that returns default value */
  value?: any | (() => any);
  
  /** Whether property changes should be reflected to attributes */
  reflectToAttribute?: boolean;
  
  /** Whether property is read-only (creates _setProperty method) */
  readOnly?: boolean;
  
  /** Whether property changes fire property-changed events */
  notify?: boolean;
  
  /** Method and dependencies for computed property */
  computed?: string;
  
  /** Observer method called when property changes */
  observer?: string;
}

/**
 * Supported property types for attribute deserialization
 */
type PropertyType = StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor;

Usage Examples:

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

class PropertyExample extends PolymerElement {
  static get is() { return 'property-example'; }
  
  static get properties() {
    return {
      // Simple string property
      name: String,
      
      // Property with default value
      count: {
        type: Number,
        value: 0
      },
      
      // Property with function default
      items: {
        type: Array,
        value: () => []
      },
      
      // Reflected property (syncs to attribute)
      active: {
        type: Boolean,
        value: false,
        reflectToAttribute: true
      },
      
      // Notify property (fires events on change)
      selectedIndex: {
        type: Number,
        value: -1,
        notify: true
      },
      
      // Read-only property
      isReady: {
        type: Boolean,
        value: false,
        readOnly: true
      },
      
      // Computed property
      displayName: {
        type: String,
        computed: 'computeDisplayName(name, count)'
      },
      
      // Property with observer
      status: {
        type: String,
        value: 'idle',
        observer: 'statusChanged'
      }
    };
  }
  
  computeDisplayName(name, count) {
    return `${name} (${count})`;
  }
  
  statusChanged(newStatus, oldStatus) {
    console.log(`Status: ${oldStatus} → ${newStatus}`);
  }
  
  // Read-only properties get _setPropertyName methods
  markReady() {
    this._setIsReady(true);
  }
}

Property Observers

Methods that are called when properties change, supporting both single and multi-property observation.

/**
 * Observer methods array for watching property changes
 */
static get observers(): string[];

Usage Examples:

class ObserverExample extends PolymerElement {
  static get is() { return 'observer-example'; }
  
  static get properties() {
    return {
      firstName: String,
      lastName: String,
      age: Number,
      address: Object,
      tags: Array
    };
  }
  
  static get observers() {
    return [
      // Multi-property observer
      'nameChanged(firstName, lastName)',
      
      // Observer with wildcard for object changes
      'addressChanged(address.*)',
      
      // Observer with array mutation watching
      'tagsChanged(tags.splices)',
      
      // Complex path observation
      'userLocationChanged(address.city, address.country)'
    ];
  }
  
  nameChanged(first, last) {
    console.log('Name changed:', first, last);
  }
  
  addressChanged(changeRecord) {
    console.log('Address property changed:', changeRecord);
  }
  
  tagsChanged(changeRecord) {
    if (changeRecord) {
      console.log('Array mutations:', changeRecord.indexSplices);
    }
  }
  
  userLocationChanged(city, country) {
    if (city && country) {
      console.log('Location:', city, country);
    }
  }
}

Attribute Synchronization

Automatic synchronization between element properties and HTML attributes.

/**
 * Properties with reflectToAttribute: true automatically sync to attributes
 * Attributes are automatically deserialized to properties based on type
 */

Usage Examples:

class AttributeSync extends PolymerElement {
  static get is() { return 'attribute-sync'; }
  
  static get properties() {
    return {
      // String attribute: <element title="Hello">
      title: {
        type: String,
        reflectToAttribute: true
      },
      
      // Boolean attribute: <element disabled> or <element disabled="">
      disabled: {
        type: Boolean,
        reflectToAttribute: true
      },
      
      // Number attribute: <element count="5">
      count: {
        type: Number,
        reflectToAttribute: true
      },
      
      // Object/Array attributes: <element data='{"key":"value"}'>
      data: {
        type: Object,
        reflectToAttribute: true
      }
    };
  }
}

// Usage in HTML:
// <attribute-sync title="Hello" disabled count="10" data='{"items":[1,2,3]}'></attribute-sync>

Property Change Events

Properties with notify: true fire events when they change, enabling two-way data binding.

/**
 * Property change events follow the pattern: property-name-changed
 * Event detail contains the new value
 */

Usage Examples:

class NotifyExample extends PolymerElement {
  static get is() { return 'notify-example'; }
  
  static get properties() {
    return {
      value: {
        type: String,
        notify: true
      }
    };
  }
  
  connectedCallback() {
    super.connectedCallback();
    
    // Listen for property change events
    this.addEventListener('value-changed', (e) => {
      console.log('Value changed to:', e.detail.value);
    });
  }
  
  updateValue() {
    this.value = 'new value'; // Fires 'value-changed' event
  }
}

// Two-way binding in templates:
// <notify-example value="{{boundProperty}}"></notify-example>

Computed Properties

Properties that are automatically calculated based on other properties.

/**
 * Computed properties are read-only and automatically updated when dependencies change
 * Format: 'methodName(dependency1, dependency2, ...)'
 */

Usage Examples:

class ComputedExample extends PolymerElement {
  static get is() { return 'computed-example'; }
  
  static get properties() {
    return {
      first: String,
      last: String,
      
      // Simple computed property
      fullName: {
        type: String,
        computed: 'computeFullName(first, last)'
      },
      
      // Computed property with complex dependencies
      summary: {
        type: String,
        computed: 'computeSummary(user.*, settings.displayMode)'
      }
    };
  }
  
  computeFullName(first, last) {
    return first && last ? `${first} ${last}` : '';
  }
  
  computeSummary(userChangeRecord, displayMode) {
    const user = userChangeRecord.base;
    if (displayMode === 'full') {
      return `${user.name} - ${user.email}`;
    }
    return user.name;
  }
}

Types

type PropertyType = StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor;

interface PropertyDeclaration {
  type?: PropertyType;
  value?: any | (() => any);
  reflectToAttribute?: boolean;
  readOnly?: boolean;
  notify?: boolean;
  computed?: string;
  observer?: string;
}

interface PropertyDeclarations {
  [property: string]: PropertyType | PropertyDeclaration;
}