Lightning Web Components Slots

Lightning web components have a lifecycle managed by the framework. The framework creates components, adds and removes them from the DOM, and renders DOM updates whenever the state of a component changes.

Lightning

There are a few steps to take before you can use your custom Lightning web components to create a Lightning page in Lightning App Builder. The Lightning App Builder is a point-and-click tool that makes it easy to create custom pages for the Salesforce mobile app and Lightning Experience, giving your users what they need all in one place. The next post also ties together several points related to slot based composition in LWC, as well as how to write good unit tests for your Lightning Web Components. Modal Usage Included in this repository is the modal as well as an example modalwrapper component that hooks into the modal. Pass Markup into Slots Add a slot to a component’s HTML file so a parent component can pass markup into the component. A component can have zero or more slots. A slot is a placeholder for markup that a parent component passes into a component’s body. Some browsers are still in the process of updating to support the standards for Web Components. In the mean time, polyfills simulate the missing browser capabilities as closely as possible. I'm trying to create a simple lightning web component that wraps a element, using an unnamed slot to populate the options. However, the options are not being rendered. If I inspect the generated DOM elements, it is just rendering slotslot as text inside the select element. If I move the slot outside of the select element, the slot.

A lifecycle hook is a JavaScript callback method triggered at a specific phase of a component instance’s lifecycle.

# Lifecycle Flow

This diagram shows the flow of the component lifecycle from creation through render.

This is the lifecycle of a component instance and its children from creation through render.

  1. constructor() is called.
  2. Public properties are updated.
  3. Component is inserted into the DOM.
  4. connectedCallback() is called.
  5. Component is rendered.
  6. constructor() is called on child components.
  7. Public properties are updated on child components.
  8. Child components are inserted into the DOM.
  9. connectedCallback() is called on child components.
  10. Child components are rendered.
  11. renderedCallback() is called on child components.
  12. renderedCallback() is called on component.

This is the lifecycle of a component instance when it's removed from the DOM.

  1. Component is removed from the DOM.
  2. disconnectedCallback() is called on the component.
  3. Children are removed from the DOM.
  4. disconnectedCallback() is called on each child.

#constructor()

The constructor() method is invoked when a component instance is created.

The constructor flows from parent to child.

To access the host element, use this.template. You can’t access child elements in the component body because they don’t exist yet. Properties are not passed yet, either. Properties are assigned to the component after construction and before the connectedCallback() hook.

Lightning Web Components Slots

These requirements from the HTML: Custom elements spec apply to the constructor().

  • The first statement must be super() with no parameters. This call establishes the correct prototype chain and value for this. Always call super() before touching this.
  • Don’t use a return statement inside the constructor body, unless it is a simple early-return (return or return this).
  • Don’t use the document.write() or document.open() methods.
  • Don’t inspect the element's attributes and children, because they don’t exist yet.
  • Don’t inspect the element’s public properties, because they’re set after the component is created.

Important

Don’t add attributes to the host element in the constructor. You can add attributes to the host element during any stage of the component lifecycle other than construction.

Slots

#connectedCallback()

The connectedCallback() lifecycle hook is invoked when a component is inserted into the DOM.

This hook flows from parent to child.

To access the host element, use this. You can’t access child elements in the component body because they don’t exist yet.

The connectedCallback() hook can fire more than once. For example, if you remove an element and then insert it into another position, such as when you reorder a list, the hook is invoked several times. If you want code to run one time, write code to prevent it from running twice.

You can use connectedCallback() to add an attribute to the host element.

You can also use connectedCallback() and disconnectedCallback() to register and unregister event listeners. The browser garbage collects DOM events, so you can choose not to unregister them. However, relying on garbage collection can lead to memory leaks. See Memory Management on MDN.

Note

To check whether a component is connected to the DOM, you can use this.isConnected.

#disconnectedCallback()

The disconnectedCallback() lifecycle hook is invoked when a component is removed from the DOM.

This hook flows from parent to child.

#render()

For complex tasks like conditionally rendering a template, use render() to override the standard rendering functionality. This function may be invoked before or after connectedCallback().

This method must return a valid HTML template. Import a reference to a template and return the reference in the render() method.

See the code sample in Render Multiple Templates.

Note

The render() method is not technically a lifecycle hook. It is a protected method on the LightningElement class. A hook usually tells you that something happened, and it may or may not exist on the prototype chain. The render() method must exist on the prototype chain.

#renderedCallback()

Note

This lifecycle hook is specific to Lightning Web Components, it isn’t from the HTML custom elements specification.

Called after every render of the component. This hook flows from child to parent.

When a component re-renders, all the expressions used in the template are reevaluated.

Due to mutations, a component is usually rendered many times during the lifespan of an application. To use this hook to perform a one-time operation, use a boolean field like hasRendered to track whether renderedCallback() has been executed. The first time renderedCallback() executes, perform the one-time operation and set hasRendered = true. If hasRendered = true, don’t perform the operation.

It’s best to attach event listeners declaratively in the HTML template. However, if you want to attach an event listener to a template element programatically in JavaScript, use renderedCallback(). If a listener is added to the same element repeatedly, the browser removes the duplicates if the event type, event listener, and options are the same.

When a template is rerendered, the LWC engine attempts to reuse the existing elements. In the following cases, the engine uses a diffing algorithm to decide whether to discard an element.

  • Elements created using the for:each directive. The decision to reuse these iteration elements depends on the key attribute. If key changes, the element may be rerendered. If key doesn’t change, the element isn’t rerendered, because the engine assumes that it didn’t change.
  • Elements received as slot content. The engine attempts to reuse an element in a <slot>, but the diffing algorithm determines whether to evict an element and recreate it.

Example

The LibsChartjs recipe in the Lightning Web Components recipes app uses the renderedCallback() lifecycle hook.

#errorCallback(error, stack)

Note

This lifecycle hook is specific to Lightning Web Components, it isn’t from the HTML custom elements specification.

Called when a descendant component throws an error in one of its lifecycle hooks. The error argument is a JavaScript native error object, and the stack argument is a string.

Implement this hook to create an error boundary component that captures errors in all the descendant components in its tree. The error boundary component can log stack information and render an alternative view to tell users what happened and what to do next. The method works like a JavaScript catch{} block for components that throw errors in their lifecycle hooks. It’s important to note that an error boundary component catches errors only from its children, and not from itself.

You can create an error boundary component and reuse it throughout an app. It’s up to you where to define those error boundaries. You can wrap the entire app, or every individual component. Most likely, your architecture falls somewhere in between. A good rule of thumb is to think about where you’d like to tell users that something went wrong.

This example implements the errorCallback() method.

You don’t have to use if:[true false] in a template. For example, let’s say you define a single component template. If this component throws an error, the framework calls errorCallback and unmounts the component during re-render.

Note

The errorCallback() hook doesn’t catch errors like click callbacks and async operations that fall outside of the component lifecycle (constructor(), connectedCallback(), render(), renderedCallback()). It’s also important to note that errorCallback() isn’t a JavaScript try/catch, it’s a component lifecycle guard.

# 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.

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>.

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.

When a component renders, the <template> tag is replaced with the namespace and name of the component. If this component were in the example namespace, the tag is <example-my-component>.

To create your template, use these techniques:

  • 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:

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 style sheet in the component bundle with the same name as the component. If the component is called myComponent, the style sheet is myComponent.css. The style sheet 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.

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.

See Share JavaScript Code.

Lightning Web Components Slots Free

# 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.

Lightning Web Components Slots No Deposit

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

Web

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.

Lightning Web Components Slots Games

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.

These are the directives supported in Lightning Web Components templates.

#for:each={array}

Use this directive to iterate over an array and render a list.

See Render Lists.

#for:index='index'

Use this directive to access 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}

Lightning Web Components Slots Free Play

Use this directive to conditionally render DOM elements in a template.

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.

#iterator:iteratorName={array}

Use this directive to apply special behavior to the first or last item in an array and render a list.

Salesforce Lightning Web Component Slot

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.

See Render Lists.

#key={uniqueId}

Use this directive to improve rendering performance by assigning a unique identifier to each item in a list. 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'

Add this directive to a native HTML element to call appendChild() on the element from the owner’s JavaScript class and preserve styling.

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.