# Reference
- Component Bundles
- JavaScript Decorators
- HTML Template Directives
- LWC Managed Elements and Directives
# Component Bundles
To create a component, create a folder that bundles your component’s files. A component folder (bundle) must live in a parent folder that defines the component's namespace. The name of the parent folder is the namespace.
A bundle can be a UI component, which renders UI, or a module, which is a library used to share code.
Tip
To understand the structure of a component and its namespace, look at the lwc-recipes-oss repo. Most components are in the recipe namespace. There are also components in the ui namespace and the data namespace. Most components are UI components. To see an example of a module, see mortgage.
# UI Components
The easiest way to create a UI component is to use the Lightning Web Components CLI, which generates boilerplate files.
A component that renders UI must have an HTML template file and a JavaScript class file. It may include a CSS file, additional JavaScript utility files, and test files. The HTML template, JavaScript class, and CSS file must have the same name. The framework uses the name to autowire the relationship between them.
mynamespace
└──myComponent
├──__tests__
| └──myComponent.test.js
├──myComponent.html
├──myComponent.js
├──shareCode.js
└──myComponent.css
The folder and its files must follow these naming rules.
- Must begin with a lowercase letter
- Must contain only alphanumeric or underscore characters
- Must be unique in the namespace
- Can’t include whitespace
- Can’t end with an underscore
- Can’t contain two consecutive underscores
- Can’t contain a hyphen (dash)
Important
Use camel case to name your component. Camel case component folder names map to kebab case in markup. Every component is part of a namespace. Use a hyphen character (-
) to separate the namespace from the component name. In markup, to reference a component in the example
namespace with the name myComponent
, use <example-my-component>
.
<template>
<example-my-component></example-my-component>
</template>
A bit more information about naming. Lightning web components match web standards wherever possible. The HTML standard requires that custom element names contain a hyphen. You can use underscores in component folder names, but they don’t map to kebab case in markup. The names are legal because the namespace is separated with a hyphen, but most developers expect hyphens instead of underscores in a web component name. For example, the component <example-my_component>
is legal, but it looks odd and may confuse developers consuming your component.
Note
The HTML spec mandates that tags for custom elements (components) aren’t self-closing. Self-closing tags end with />
. Therefore, <example-my-component>
includes a closing </example-my-component>
tag.
# HTML File
Every UI component must have an HTML file with the root tag <template>
.
The HTML file follows the naming convention <component>.html
, such as myComponent.html
.
Create the HTML for a Lightning web component declaratively, within the <template>
tag. The HTML template element contains your component’s HTML.
<!-- myComponent.html -->
<template>
<!-- Your markup here -->
</template>
When a component renders, the <template>
tag is replaced with the namespace and name of the component. If this component is in the example
namespace, the tag is <example-my-component>
.
To create your template, use these techniques:
- Render DOM elements conditionally
- Render lists
- Create slots that component consumers can replace with content.
# JavaScript File
Every UI component must have a JavaScript file, which is a class that defines the HTML element.
The JavaScript file follows the naming convention <component>.js
, such as myComponent.js
.
This class must include at least this code:
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {}
The core module is lwc
. The import
statement imports LightningElement
from the lwc
module. LightningElement
is a custom wrapper of the standard HTML element.
The convention is for the class name to be Pascal Case, where the first letter of each word is capitalized. For myComponent.js
, the class name is MyComponent
.
Extend LightningElement
to create a JavaScript class for a Lightning web component. The export default
keywords export a MyComponent
class for other components to use.
JavaScript files in Lightning web components are ES6 modules. By default, everything declared in a module is local—it’s scoped to the module.
The JavaScript class can contain:
- The component’s public API via public properties and methods annotated with
@api
. - Private properties
- Event handlers
In addition to this JavaScript file that creates the HTML element, a UI component’s folder can contain other JavaScript files that are used to share code. These utility JavaScript files must be ES6 modules and must have names that are unique within the component’s folder.
See Reactive Properties and Properties and Attributes.
# CSS File
A component can include a CSS file. Use standard CSS syntax to style Lightning web components.
To style a component, create a stylesheet in the component bundle with the same name as the component. If the component is called myComponent
, the stylesheet is myComponent.css
. The stylesheet is applied automatically.
See CSS.
# Test Files
To create Jest tests for a component, create a folder called __tests__
at the top level of the component’s folder. Save the tests inside the __tests__
folder.
Jest runs JavaScript files in the __tests__
directory. Test files must have names that end in .js
, and we recommend that tests end in .test.js
. You can have a single test file with all of your component tests, or you can have multiple files to organize related tests. Test files can be placed in sub folders.
See Unit Tests.
# Modules
To share code between components, create an ES6 module and export the variables or functions that you want to expose.
mynamespace
└──myLibrary
└──myLibrary.js
The module folder and file name must follow the same naming conventions as a UI component.
An ES6 module is a file that explicitly exports functionality that other modules can use. Modules make it easier to structure your code without polluting the global scope.
Within a JavaScript class, to reference a module, use namespace/module
. The forward slash character (/
) separates the namespace from the module name.
import { LightningElement } from 'lwc';
import { NamedExport } from 'acme/myLibrary';
import DefaultExport from 'acme/myLibrary';
export default class Example extends LightningElement {}
# JavaScript Decorators
Decorators add functionality to a property or function. The ability to create decorators is part of ECMAScript, but these decorators are unique to Lightning Web Components.
# @api
To expose a public property, decorate a field with @api
. Public properties define the API for a component. An owner component that uses the component in its HTML markup can access the component’s public properties via HTML attributes.
Public properties are reactive. If the value of a property changes, the component’s template re-renders any content that references the property. For more information, see Public Properties.
To expose a public method, decorate it with @api
. Public methods also define the API for a component. To communicate down the component hierarchy, owner and parent components can call JavaScript methods on child components.
# @track
All fields are reactive. When the framework observes a change to a field used in a template or used in the getter of a property used in a template, the component re-renders. However, there is a limit to the depth of changes that the framework observes.
If a field contains an object value or an array value, the framework observes changes that assign a new value to the field. If the value that you assign to the field is not ===
to the previous value, the component re-renders.
Decorate a field with @track
to tell the framework to observe changes to the properties of an object or to the elements of an array.
For code samples, see Field Reactivity.
# @wire
LWC has an elegant way to provide a stream of data to a component. Declare a component's data requirements in a wire adapter. Use the @wire
decorator to connect or wire a component to the wire adapter.
Wire adapters are a statically analyzable expression of data. Wire adapters can also have dynamic configuration parameters. If a configuration value changes, new data is provisioned and the component rerenders.
See Wire Adapters.
# HTML Template Directives
Write templates using standard HTML and a few directives that are unique to Lightning Web Components. Directives are special HTML attributes that add dynamic behavior to an HTML template. Directives give you more power to manipulate the DOM in markup.
You can use certain directives on a root <template>
tag, a nested <template>
tag, an HTML element such as a <p>
tag, or a custom component tag. These directives are supported in Lightning Web Components templates.
# Directives for Root Templates
A root <template>
tag is the first element in a component's HTML template. It supports the following directives.
# lwc:preserve-comments
Preserves HTML comments so that they are rendered in the DOM. For example, you can use conditional comments to improve design and styling in specific browsers.
<template lwc:preserve-comments>
<!-- This comment is preserved in the DOM -->
<h2>Hello HTML comments!</h2>
<template lwc:if={display}>
<!-- More comments in a nested template -->
Hello again!
</template>
</template>
When lwc:preserve-comments
is enabled, you can't place comments between sibling conditional directives.
<!-- Invalid -->
<template lwc:preserve-comments>
<template lwc:if={property}></template>
<!-- Remove this comment -->
<template lwc:else></template>
</template>
HTML comments don't support data bindings.
Note
For more information see rfcs.lwc.dev/rfcs/lwc/0000-template-comments.
# lwc:render-mode='light'
Renders a component using light DOM, which enables third-party tools to traverse the DOM using standard browser query APIs such as querySelector
.
# Directives for Nested Templates
A component's template can include nested <template>
tags with certain directives. These nested tags support only the following directives.
# for:each={array}
Iterates over an array and renders a list. Also supported for use with HTML elements.
<template for:each={items} for:item="item">
<div>{item}</div>
</template>
The equivalent inline format is as follows.
<div for:each={items} for:item="item">{item}</div>
See Render Lists.
# for:index="index"
Accesses the current item's zero-based index.
The index
placeholder is a new identifier that the model injects into the current scope.
See Render Lists.
# if:true|false={expression}
Deprecated. The if:true
and if:false
directives are no longer recommended. They may be deprecated and removed in the future. Use lwc:if
, lwc:elseif
, and lwc:else
instead.
if:true|false={expression}
conditionally renders DOM elements in a template, calling the expression
for each of if:true
and if:false
. In cases where you chain if:true
and if:false
directives, they may not be as performant or as lightweight as the lwc:if
, lwc:elseif
, and lwc:else
directives.
The expression
can be a JavaScript identifier (for example, person
) or dot notation that accesses a property from an object (person.firstName
). The engine doesn’t allow computed expressions (person[2].name['John']
). To compute the value of expression
, use a getter in the JavaScript class.
See Render DOM Elements Conditionally.
# lwc:if|elseif={expression}
and lwc:else
Conditionally render DOM elements in a template. lwc:if
, lwc:elseif
, and lwc:else
supersede the if:true
and if:false
directives.
Use the conditional directives on nested <template>
tags, <div>
tags or other HTML elements, and on your custom components tags like <c-custom-cmp>
.
Both lwc:elseif
and lwc:else
must be immediately preceded by a sibling lwc:if
or lwc:elseif
.
<template lwc:if={expression}></template>
<template lwc:else></template>
Both lwc:if
and lwc:elseif
must evaluate an expression. However, lwc:else
must not have an attribute value.
<template lwc:if={expression}></template>
<template lwc:elseif={expression_elseif1}></template>
<template lwc:elseif={expression_elseif2}></template>
<template lwc:else></template>
The expression passed in to lwc:if
and lwc:elseif
supports simple dot notation. Complex expressions like !condition
, object?.property?.condition
or sum % 2 === 1
aren't supported. To compute such expressions, use a getter in the JavaScript class.
Note
The expressions and property getters are only accessed once per instance of an lwc:if
or lwc:elseif
.
In the above case, if expression
is truthy, then none of the other property getters are accessed.
You can't precede lwc:elseif
or lwc:else
with text or another element. Whitespace is ignored between the tags when the whitespace is a sibling of the conditional directive. For example you can't have a <div>
tag that comes after lwc:if
and before lwc:else
.
<!-- Invalid -->
<template lwc:if={expression}></template>
This text node makes the pattern invalid
<div>This div tag makes the pattern invalid</div>
<template lwc:else></template>
Code comments can be included as a sibling of the conditional directive only if lwc:preserve-comments
isn't enabled. See lwc:preserve-comments.
Note
You can also use the conditional directive to render a <slot>
. See Pass Markup into Slots.
To check for a falsy, pass in the negation operator in your getter's return value so the expression
is true
.
<template lwc:if={notCondition}></template>
get notCondition() {
return !this.condition;
}
Note
lwc:if
, lwc:elseif
, and lwc:else
can't be applied to the same element and they cannot be combined with the if:true
and if:false
directives.
See Render DOM Elements Conditionally.
# iterator:iteratorname={array}
Applies special behavior to the first or last item in an array and render a list. Also supported for use with HTML elements. iteratorname
must be in lowercase.
Access these properties on the iteratorname
:
value
—The value of the item in the list. Use this property to access the properties of the array. For example,iteratorname.value.propertyName
.index
—The index of the item in the list.first
—A boolean value indicating whether this item is the first item in the list.last
—A boolean value indicating whether this item is the last item in the list.
<ul>
<template iterator:it={list}>
<li key={it.value}>{it.value}</li>
</template>
</ul>
The equivalent inline format is as follows.
<ul iterator:it={list}>
<li key={it.value}>{it.value}</li>
</ul>
See Render Lists.
# lwc:slot-data
Links the scoped slot fragment in a parent component to the lwc:slot-bind
directive in a child component. The child component must use light DOM.
Add lwc:slot-data
to the <template>
element in the parent component and set the value of lwc:slot-data
to a string literal. The <template lwc:slot-data>
element must be a direct child of a custom element.
The string literal for lwc:slot-data
and the variable used by the corresponding lwc:slot-bind
don't have to share the same name.
A <template>
element can have only one instance of lwc:slot-data
. A scoped slot fragment binds to only one child component.
# Directives for Slots
A <slot>
tag supports the following directives.
# lwc:slot-bind
This directive binds data to the scoped slot in a child component. The child component must use light DOM.
Add lwc:slot-bind
to the <slot>
element of the child component and set the value of lwc:slot-bind
to a variable name. The <slot lwc:slot-bind>
element can only be used in a light DOM element's HTML <template>
.
You can add only one instance of lwc:slot-bind
to a <slot>
element. A scoped slot can bind to only one source of data.
# Directives for HTML Elements
You can use certain directives on an HTML element, such as on a <p>
tag, a base component, or your own custom component.
The lwc:if
, lwc:elseif
, and lwc:else
directives in the previous section are also supported for use with HTML tags, a base component, or your own custom component.
# for:each={array}
Iterates over an array and renders a list. Also supported for use with nested templates.
<div for:each={items} for:item="item">
{item}
</div>
See Render Lists.
# iterator:iteratorname={array}
Applies special behavior to the first or last item in an array and render a list. Also supported for use with nested templates.
# key={uniqueId}
Improves rendering performance by assigning a unique identifier to each item in a list. Use this directive with iterator:iteratorname={array}
or for:each={array}
.
The key
must be a string or a number, it can’t be an object. The engine uses the keys to determine which items have changed.
See Render Lists.
# lwc:dom="manual"
Enables content to be manually appended to an element. For example, use lwc:dom="manual"
if you're integrating a third-party library and want to implement styling on the manually inserted element with the host styles. Alternatively, use lwc:inner-html={HTMLContent}
for dynamic HTML injection in both browser and server-side rendering.
To append content, add lwc:dom="manual"
to an empty native HTML element to call appendChild()
on the element from the owner’s JavaScript class and preserve styling.
<template>
<div class="container" lwc:dom="manual"></div>
</template>
Add the HTML content to the element in your component's JavaScript.
import { LightningElement } from 'lwc';
const CONTAINER_HTML = `<div>Some HTML</div>`;
export default class extends LightningElement {
renderCallback() {
const container = this.template.querySelector('.container');
container.innerHTML = CONTAINER_HTML;
// Do something
}
}
If a call to appendChild()
manipulates the DOM, styling isn’t applied to the appended element. Using JavaScript to manipulate the DOM isn’t recommended when programming Lightning web components, but some third-party JavaScript libraries require it.
See Third-Party JavaScript Libraries.
# lwc:dynamic={componentConstructor}
(Deprecated)
lwc:dynamic
is deprecated and no longer recommended for instantiating a component dynamically. Use the <lwc:component>
managed element with the lwc:is
directive instead.
<lwc:component lwc:is={componentConstructor}></lwc:component>
To replace your usage of lwc:dynamic
with lwc:is
, consider these guidelines.
-
With
lwc:is
, the dynamic component's name is created at compile time. At runtime, the custom element name is retrieved and used for each constructor. Solwc:is
renders the dynamic component using the name of the dynamic component that's created at runtime. Contrastingly,lwc:dynamic
requires you to define a custom element name to use as the name for all constructors passed tolwc:dynamic
. -
lwc:dynamic
behaves similarly tolwc:is
when the constructor is not provided; the dynamic component and its children are not rendered.
Note
The deprecated behavior is described in the Dynamic Imports RFC.
# lwc:inner-html={HTMLContent}
Note
This directive is not available to external developers building Lightning web components on the Salesforce Platform.
Enables raw HTML content to be injected via JavaScript or for server-side rendered components. In synthetic shadow, lwc:inner-html
relies on the same mechanism as lwc:dom="manual"
to apply scoped styles to the manually injected content.
<template>
<div lwc:inner-html={content}></div>
</template>
import { LightningElement } from 'lwc';
export default class Example extends HTMLElement {
content = 'Hello <strong>world</strong>!';
}
The lwc:inner-html
directive cannot be applied to:
- Boolean attributes
- HTML elements with child nodes
- LWC components (e.g.
<c-my-cmp>
etc.) <slot>
<template>
The following are valid use cases.
<template>
<div lwc:inner-html={content}></div>
<div lwc:inner-html="<h1>hello</h1>"></div>
</template>
The following examples are invalid.
<template>
<!-- Invalid -->
<div lwc:inner-html></div>
<div lwc:inner-html={content}>With content</div>
<slot lwc:inner-html={content}></slot>
<template lwc:inner-html={content}></template>
<x-foo lwc:inner-html={content}></x-foo>
</template>
Use this directive with the sanitizeHtmlContent()
hook to sanitize the content passed to the directive. Override this hook using setHooks
.
# lwc:ref
Refs locate DOM elements without a selector and query elements in a specified <template></template>
only.
To use refs, add the lwc:ref
directive to your element and assign it a value. To call that reference, use this.refs
. In this example, this.refs
references the directive lwc:ref="myDiv"
to access the <div>
at runtime.
<template>
<div lwc:ref="myDiv"></div>
</template
export default class extends LightningElement {
renderedCallback() {
console.log(this.refs.myDiv);
}
}
We recommend that you use this.refs
instead of this.template.querySelector()
in shadow DOM or this.querySelector()
in light DOM. For shadow DOM components, this.refs
refers to elements inside of the shadow DOM. For light DOM components, this.refs
refers to elements inside of the light DOM. If lwc:ref
is not defined in the template, then this.refs
returns undefined.
See Access Elements the Component Owns.
# lwc:spread={childProps}
Spreads properties to a child component, enabling lwc:component
and other elements to accept an object that's bound as props at runtime.
Define your properties in your component's JavaScript.
// c/myComponent.js
import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
childProps = {
name: "My child property",
};
}
Apply childProps
as a property to c-child
. Only one instance of lwc:spread
on a directive is allowed.
<!-- c/myComponent.html -->
<template>
<c-child lwc:spread={childProps}></c-child>
</template>
See Spread Properties to a Child Component.
# lwc:external
Note
lwc:external
isn't currently supported on the Salesforce Platform. Using a web component from another framework is not supported.
Enables a native web component, also known as an external component or custom element, to be used in an LWC app. Adding this directive to an external component enables it to be resolved by the browser instead of the LWC compiler. Alternatively, you can use custom elements in an LWC template file using lwc:dom="manual"
.
To use a custom native-component
element, add it to your template using lwc:external
.
<!-- app.html -->
<template>
<my-custom-element lwc:external></my-custom-element>
</template>
With lwc:external
, you don't need to import or inject the external component in the template.
The lwc:external
directive cannot be applied to:
- Boolean attributes
- HTML elements (e.g.
<div>
and<span>
) - LWC components (e.g.
<c-my-cmp>
etc.) <slot>
<template>
See Third-Party Web Components.
# LWC Managed Elements and Directives
LWC managed elements are components that are created and managed by the LWC engine to enhance your development. Only the <lwc:component>
managed element and lwc:is
directive are currently supported.
# <lwc:component>
Enables importing and instantiating a component dynamically. Dynamic instantiation refers to creating a component instance when the underlying component constructor isn't known until run time.
<lwc:component>
serves as a placeholder in the DOM that renders the specified dynamic component. You must use <lwc:component>
with the lwc:is
directive.
To enable component creation with <lwc:component>
and lwc:is
, set lwc({ enableDynamicComponents: true })
in the compiler option.
<lwc:component>
can also be used with directives for nested templates.
See Create a Component Dynamically.
# lwc:is={componentConstructor}
Provides a constructor at runtime to the <lwc:component>
managed element for dynamic component creation.
<template>
<div class="container">
<lwc:component lwc:is={componentConstructor}></lwc:component>
</div>
</template>
lwc:is
accepts an expression that resolves to a LightningElement
constructor at runtime. When this value changes, the component and all its children are destroyed and recreated using the new constructor.
If the constructor is falsy, the <lwc:component>
tag along with all of its children are not rendered.
If the expression value is defined but not a LightningElement
constructor, an error is thrown.
lwc:is
can be used with the lwc:spread
and lwc:ref
directives. Additionally, lwc:is
can only be used with the <lwc:component>
managed element.
lwc:is
cannot be used with these directives:
lwc:external
lwc:inner-html
lwc:is
cannot be applied to:
- HTML elements (
<div>
and<span>
etc.) - LWC components (
<c-my-cmp>
etc.) - Root and nested templates
See Create a Component Dynamically.