You're viewing docs for an older version of Lit. Click here for the latest version.

Properties

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

  • Ensure that an element update is scheduled when any declared property changes.
  • Capture instance values for declared properties. Apply any property values that are set before the browser registers a custom element definition.
  • Set up an observed (not reflected) attribute with the lowercased name of each property.
  • Handle attribute conversion for properties declared as type String, Number, Boolean, Array, and Object.
  • Use direct comparison (oldValue !== newValue) to test for property changes.
  • Apply any property options and accessors declared by a superclass.

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.

Declare your element's properties using a static properties field, or using decorators:

Properties field

static get properties() {
  return {
    propertyName: options
  };
}

Decorator (requires TypeScript or Babel)

export class MyElement extends LitElement {
  @property(options)
  propertyName;

In either case, you can pass an options object to configure features for the property.

The options object can have the following properties:

attribute

Whether the property is associated with an attribute, or a custom name for the associated attribute. Default: true. See Configure observed attributes. If attribute is false, the converter, reflect and type options are ignored.

converter

A custom converter for converting between properties and attributes. If unspecified, use the default attribute converter.

hasChanged

A function that takes an oldValue and newValue and returns a boolean to indicate whether a property has changed when being set. If unspecified, LitElement uses a strict inequality check (newValue !== oldValue) to determine whether the property value has changed.

noAccessor

Set to true to avoid generating the default property accessor. Default: false.

reflect

Whether property value is reflected back to the associated attribute. Default: false. See Configure reflected attributes.

type

A type hint for converting between properties and attributes. This hint is used by LitElement's default attribute converter, and is ignored if converter is set. If type is unspecified, behaves like type: String. See Use LitElement's default attribute converter.

An empty options object is equivalent to specifying the default value for all options.

An options object by another name. This guide uses the descriptive term "options object." In practice the options object is an instance of PropertyDeclaration, so you'll see that name if you're using an IDE, or looking at the API reference. By either name, it's an object that defines a set of options.

Declare properties in a static properties field

Permalink to “Declare properties in a static properties field”

To declare properties in a static properties field:

An empty option object is equivalent to specifying the default value for all options.

Declared properties are initialized like standard class fields—either in the constructor, or with a field initializer if you're using decorators.

Example: Declare properties with a static properties field

Code Editor not supported on this browser

Use the @property decorator to declare properties (instead of the static properties field).

The argument to the @property decorator is an options object. Omitting the argument is equivalent to specifying the default value for all options.

Using decorators. Decorators are a proposed JavaScript feature, so you'll need to use a transpiler like Babel or the TypeScript compiler to use decorators. See Using decorators for details.

There is also an @internalProperty decorator for private or protected properties that should trigger an update cycle. Properties declared with @internalProperty shouldn't be referenced from outside the component.

The @internalProperty decorator automatically sets attribute to false; the only option you can specify for an internal property is the hasChanged function.

The @internalProperty decorator can serve as a hint to a code minifier that the property name can be changed during minification.

Example: Declare properties with decorators

Code Editor not supported on this browser

A property change can trigger an asynchronous update cycle, which causes the component to re-render its template.

When a property changes, the following sequence occurs:

  1. The property's setter is called.
  2. The setter calls the property's hasChanged function. The hasChanged function takes the property's old and new values, and returns true if the change should trigger an update. (The default hasChanged uses a strict inequality test (oldValue !== newValue) to determine if the property has changed.)
  3. If hasChanged returns true, the setter calls requestUpdate to schedule an update. The update itself happens asynchronously, so if several properties are updated at once, they only trigger a single update.
  4. The component's update method is called, reflecting changed properties to attributes and re-rendering the component's templates.

There are many ways to hook into and modify the update lifecycle. For more information, see Lifecycle.

Typically, you initialize property values in the element constructor.

When using decorators, you can initialize the property value as part of the declaration (equivalent to setting the value in the constructor).

You may want to defer initializing a property if the value is expensive to compute and is not required for the initial render of your component. This is a fairly rare case.

Initialize property values in the element constructor

Permalink to “Initialize property values in the element constructor”

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

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

Example: Initialize property values in the element constructor

Code Editor not supported on this browser

Initialize property values when using decorators

Permalink to “Initialize property values when using decorators”

When using the @property decorator, you can initialize a property as part of the declaration:

Example: Initialize property values when using decorators

Code Editor not supported on this browser

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

  • To observe an attribute (set a property from an attribute), the attribute value must be converted from a string to match the property type.

  • To reflect an attribute (set an attribute from a property), the property value must be converted to a string.

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:

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

Convert from attribute to property

  • For Strings, when the attribute is defined, set the property to the attribute value.
  • For Numbers, when the attribute is defined, set the property to Number(attributeValue).
  • For Booleans, when the attribute is:
    • non-null, set the property to true.
    • null or undefined, set the property to false.
  • For Objects and Arrays, when the attribute is:
    • Defined, set the property value to JSON.parse(attributeValue).

Convert from property to attribute

  • For Strings, when the property is:
    • null, remove the attribute.
    • undefined, don't change the attribute.
    • Defined and not null, set the attribute to the property value.
  • For Numbers, when the property is:
    • null, remove the attribute.
    • undefined, don't change the attribute.
    • Defined and not null, set the attribute to the property value.
  • For Booleans, when the property is:
    • truthy, create the attribute.
    • falsy, remove the attribute.
  • For Objects and Arrays, when the property is:
    • null or undefined, remove the attribute.
    • Defined and not null, set the attribute value to JSON.stringify(propertyValue).

Example: Use the default converter

Code Editor not supported on this browser

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

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

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

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

During an update:

  • If toAttribute returns null, the attribute is removed.

  • If toAttribute returns undefined, the attribute is not changed.

Example: Configure a custom converter

Code Editor not supported on this browser

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:

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

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.

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

Code Editor not supported on this browser

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

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

  • If toAttribute returns null, the attribute is removed.

  • If toAttribute returns undefined, the attribute is not changed.

  • If toAttribute itself is undefined, the attribute value is set to the property value without conversion.

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

Code Editor not supported on this browser

Set property values from attributes in markup

Permalink to “Set property values from attributes in markup”

If a property is configured with attribute: true (the default), users can set the property values from observed attributes in static markup:

index.html

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

Attributes versus property bindings. Setting a static attribute value is not the same as binding to a property. See Bind to a property.

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

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

To specify how getting and setting works for a property, you can define your getter/setter pair. For example:

If your class defines its own accessors for a property, LitElement will not overwrite them with generated accessors. If your class does not define accessors for a property, LitElement will generate them, even if a superclass has defined the property or accessors.

The setters that LitElement generates automatically call requestUpdate. If you write your own setter you must call requestUpdate manually, supplying the property name and its old value.

Example

A common pattern for accessors is to store the property value using a private property that's only accessed inside the component. This example uses an underscore prefix (_prop) to identify the private property—you could also use TypeScript's private or protected keywords.

If you want to use your own property accessor with the @property decorator, you can achieve this by putting the decorator on the getter:

Prevent LitElement from generating a property accessor

Permalink to “Prevent LitElement from generating a property accessor”

In rare cases, a subclass may need to change or add property options for a property that exists on its superclass.

To prevent LitElement from generating a property accessor that overwrites the superclass's defined accessor, set noAccessor to true in the property declaration:

You don't need to set noAccessor when defining your own accessors.

Example

Subclass element

Code Editor not supported on this browser

All declared properties have a function, hasChanged, which is called when 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:

  • hasChanged returns true if newVal !== oldVal.
  • hasChanged returns false if both the new and old values are NaN.

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

hasChanged may not be called for every change. If a property's hasChanged returns true once, it won't be called again until after the next update, even if the property is changed multiple times. If you want to be notified each time a property is set, you should create a custom setter for the property, as described in Create your own property accessors.

Example: Configure property changes

Code Editor not supported on this browser