{::options toc_levels="1..3" /} * ToC {:toc}

Overview {#overview}

LitElement manages your declared properties and their corresponding attributes. By default, LitElement will:

{:.alert .alert-warning}

Remember to declare all of the properties that you want LitElement to manage. For the property features above to be applied, you must declare the property.

Property options

A property declaration is an object in the following format:

{ optionName1: optionValue1, optionName2: optionValue2, ... }

The following options are available:

All property declaration options can be specified in a static properties getter, or with TypeScript decorators.

Declare properties {#declare}

Declare your element's properties by implementing a static properties getter, or by using TypeScript decorators:

// properties getter
static get properties() {
  return { 
    prop1: { type: String }
  };
}
// TypeScript decorators
export class MyElement extends LitElement {
  @property( { type : String }  ) prop1 = '';

Declare properties in a static properties getter

To declare properties in a static properties getter:

static get properties() { 
  return { 
    prop1: { type: String },
    prop2: { type: Number },
    prop3: { type: Boolean }
  };
}

{:.alert .alert-warning}

If you implement a static properties getter, initialize your property values in the element constructor.

constructor() {
  // Always call super() first
  super();
  this.prop1 = 'Hello World';
  ...
}

Remember to call super() first in your constructor, or your element won't render at all.

Example: Declare properties with a static properties getter

{% include projects/properties/declare/my-element.js %}

{% include project.html folder="properties/declare" openFile="my-element.js" %}

Declare properties with TypeScript decorators

You can also declare properties with TypeScript decorators:

@property({type : String})  prop1 = 'Hello World';

Example: Declare properties with TypeScript decorators

{% include projects/properties/declaretypescript/my-element.ts %}

{% include project.html folder="properties/declaretypescript" openFile="my-element.ts" %}

Initialize property values {#initialize}

Initialize property values in the element constructor

If you implement a static properties getter, initialize your property values in the element constructor:

static get properties() { return { /* Property declarations */ }; } 

constructor() {
  // Always call super() first
  super();

  // Initialize properties 
  this.prop1 = 'Hello World';
}

{:.alert .alert-warning}

Remember to call super() first in your constructor, or your element won't render at all.

Example: Initialize property values in the element constructor

{% include projects/properties/init/my-element.js %}

{% include project.html folder="properties/init" openFile="my-element.js" %}

Initialize property values when using TypeScript decorators

TypeScript users can initialize property values when they are declared with the @property decorator:

@property({ type : String }) prop1 = 'Hello World';

Example: Initialize property values when using TypeScript decorators

{% include projects/properties/inittypescript/my-element.ts %}

{% include project.html folder="properties/inittypescript" openFile="my-element.ts" %}

Initialize property values from attributes in markup

You can also initialize property values from observed attributes in markup:

index.html

<my-element 
  mystring="hello world"
  mynumber="5"
  mybool
  myobj='{"stuff":"hi"}'
  myarray='[1,2,3,4]'></my-element>

{% include project.html folder="properties/initmarkup" openFile="index.html" %}

See observed attributes and converting between properties and attributes for more information on setting up initialization from attributes.

Configure attributes {#attributes}

Convert between properties and attributes {#conversion}

While element properties can be of any type, attributes are always strings. This impacts the observed attributes and reflected attributes of non-string properties:

Use the default converter {#conversion-type}

LitElement has a default converter which handles String, Number, Boolean, Array, and Object property types.

To use the default converter, specify the type option in your property declaration:

// Use LitElement's default converter 
prop1: { type: String },
prop2: { type: Number },
prop3: { type: Boolean },
prop4: { type: Array },
prop5: { type: Object }

The information below shows how the default converter handles conversion for each type.

Convert from attribute to property

Convert from property to attribute

Example: Use the default converter

{% include projects/properties/defaultconverter/my-element.js %}

{% include project.html folder="properties/defaultconverter" openFile="my-element.js" %}

Configure a custom converter {#conversion-converter}

You can specify a custom property converter in your property declaration with the converter option:

myProp: { 
  converter: // Custom property converter
} 

converter can be an object or a function. If it is an object, it can have keys for fromAttribute and toAttribute:

prop1: { 
  converter: { 
    fromAttribute: (value, type) => { 
      // `value` is a string
      // Convert it to a value of type `type` and return it
    },
    toAttribute: (value, type) => { 
      // `value` is of type `type` 
      // Convert it to a string and return it
    }
  }
}

If converter is a function, it is used in place of fromAttribute:

myProp: { 
  converter: (value, type) => { 
    // `value` is a string
    // Convert it to a value of type `type` and return it
  }
} 

If no toAttribute function is supplied for a reflected attribute, the attribute is set to the property value without conversion.

During an update:

Example: Configure a custom converter

{% include projects/properties/attributeconverter/my-element.js %}

{% include project.html folder="properties/attributeconverter" openFile="my-element.js" %}

Configure observed attributes {#observed-attributes}

An observed attribute fires the custom elements API callback attributeChangedCallback whenever it changes. By default, whenever an attribute fires this callback, LitElement sets the property value from the attribute using the property's fromAttribute function. See Convert between properties and attributes for more information.

By default, LitElement creates a corresponding observed attribute for all declared properties. The name of the observed attribute is the property name, lowercased:

// observed attribute name is "myprop"
myProp: { type: Number }

To create an observed attribute with a different name, set attribute to a string:

// Observed attribute will be called my-prop
myProp: { attribute: 'my-prop' }

To prevent an observed attribute from being created for a property, set attribute to false. The property will not be initialized from attributes in markup, and attribute changes won't affect it.

// No observed attribute for this property
myProp: { attribute: false }

An observed attribute can be used to provide an initial value for a property via markup. See Initialize properties with attributes in markup.

Example: Configure observed attributes

{% include projects/properties/attributeobserve/my-element.js %}

{% include project.html folder="properties/attributeobserve" openFile="my-element.js" %}

Configure reflected attributes {#reflected-attributes}

You can configure a property so that whenever it changes, its value is reflected to its observed attribute. For example:

// Value of property "myProp" will reflect to attribute "myprop"
myProp: { reflect: true }

When the property changes, LitElement uses the toAttribute function in the property's converter to set the attribute value from the new property value.

{:.alert .alert-info}

LitElement tracks reflection state during updates. LitElement keeps track of state information to avoid creating an infinite loop of changes between a property and an observed, reflected attribute.

Example: Configure reflected attributes

{% include projects/properties/attributereflect/my-element.js %}

{% include project.html folder="properties/attributereflect" openFile="my-element.js" %}

Configure property accessors {#accessors}

By default, LitElement generates a property accessor for all declared properties. The accessor is invoked whenever you set the property:

// Declare a property
static get properties() { return { myProp: { type: String } }; }
...
// Later, set the property
this.myProp = 'hi'; // invokes myProp's generated property accessor

Generated accessors automatically call requestUpdate, initiating an update if one has not already begun.

Create custom property accessors {#accessors-custom}

To specify how getting and setting works for a property, create custom accessors:

// Declare a property
static get properties() { return { myProp: { type: String } }; }

// Custom accessors
set myProp(value) { ... /* Custom setter */ } 
get myProp() { ... /* Custom getter */ }

...

// Later, set the property
this.myProp = 'hi'; // Invokes generated accessor, which calls custom accessor

When you create custom property accessors for a property, LitElement still generates its own accessors unless you specify otherwise (see below). The generated setter:

Prevent LitElement from generating a property accessor {#accessors-noaccessor}

To prevent LitElement from generating property accessors, set noAccessors to true in the property declaration:

static get properties() { return { 
  // Don't generate accessors for myProp
  myProp: { type: Number, noAccessors: true } 

  // Do generate accessors for aProp
  aProp: { type: String }
}; }

// Create custom accessors for myProp
set myProp(value) { this._myProp = Math.floor(value); } 
get myProp() { return this._myProp; }

updated(changedProperties) { ... /* no changedProperties entry for myProp */ }

...
// later...
this.myProp = Math.random()*10; // Invokes custom setter; no generated setter
this.aProp = 'hi'; // Invokes generated setter

In the example above:

To handle update requests and property options in a custom setter, call this.requestUpdate('propertyName', oldValue):

set myProp(value) { 
  let oldValue = this._myProp;
  this._myProp = Math.floor(value); 
  this.requestUpdate('myProp', oldValue);
} 

Example: Custom property accessors

{% include projects/properties/customsetter/my-element.js %}

{% include project.html folder="properties/customsetter" openFile="my-element.js" %}

Configure property changes

All declared properties have a function, hasChanged, which is called whenever the property is set.

hasChanged compares the property's old and new values, and evaluates whether or not the property has changed. If hasChanged returns true, LitElement starts an element update if one is not already scheduled. See the Element update lifecycle documentation for more information on how updates work.

By default:

To customize hasChanged for a property, specify it as a property option:

myProp: { hasChanged(newVal, oldVal) {
  // compare newVal and oldVal
  // return `true` if an update should proceed
}}

Example: Configure property changes

{% include projects/properties/haschanged/my-element.js %}

{% include project.html folder="properties/haschanged" openFile="my-element.js" %}