Properties
Overview
Permalink to “Overview”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
, andObject
. - 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 properties
Permalink to “Declare properties”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.
Property options
Permalink to “Property options”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, theconverter
,reflect
andtype
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
andnewValue
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. Iftype
is unspecified, behaves liketype: String
. See Use LitElement's default attribute converter.- The property's setter is called.
- The setter calls the property's
hasChanged
function. ThehasChanged
function takes the property's old and new values, and returns true if the change should trigger an update. (The defaulthasChanged
uses a strict inequality test (oldValue !== newValue
) to determine if the property has changed.) - If
hasChanged
returns true, the setter callsrequestUpdate
to schedule an update. The update itself happens asynchronously, so if several properties are updated at once, they only trigger a single update. - The component's
update
method is called, reflecting changed properties to attributes and re-rendering the component's templates. 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.
- 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 totrue
. null
orundefined
, set the property tofalse
.
- non-
- For Objects and Arrays, when the attribute is:
- Defined, set the property value to
JSON.parse(attributeValue)
.
- Defined, set the property value to
- 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
orundefined
, remove the attribute.- Defined and not
null
, set the attribute value toJSON.stringify(propertyValue)
.
If
toAttribute
returnsnull
, the attribute is removed.If
toAttribute
returnsundefined
, the attribute is not changed.If
toAttribute
returnsnull
, the attribute is removed.If
toAttribute
returnsundefined
, the attribute is not changed.If
toAttribute
itself is undefined, the attribute value is set to the property value without conversion.hasChanged
returnstrue
ifnewVal !== oldVal
.hasChanged
returnsfalse
if both the new and old values areNaN
.
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
Declare properties with decorators
Permalink to “Declare properties with decorators”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
What happens when properties change
Permalink to “What happens when properties change”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:
There are many ways to hook into and modify the update lifecycle. For more information, see Lifecycle.
Initialize property values
Permalink to “Initialize property values”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
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
Configure attributes
Permalink to “Configure attributes”Convert between properties and attributes
Permalink to “Convert between properties and attributes”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
Permalink to “Use the default converter”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
Convert from property to attribute
Example: Use the default converter
Configure a custom converter
Permalink to “Configure a custom converter”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:
Example: Configure a custom converter
Configure observed attributes
Permalink to “Configure 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:
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
Configure reflected attributes
Permalink to “Configure reflected attributes”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.
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
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.
Configure property accessors
Permalink to “Configure property accessors”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.
Create your own property accessors
Permalink to “Create your own property accessors”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
Configure property changes
Permalink to “Configure property changes”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:
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