Build Custom Forms in Native Shadow DOM
AVAILABLE API VERSIONS |
---|
Available in LWC API v61.0 and later |
When working with Salesforce data, you can use the lightning-record-form
, lightning-record-edit
, or lightning-record-view
base components to easily provide a form-based UI for data input or display. You can also build a custom UI using the Lightning Data Service wire adapters.
ElementInternals
applies to light DOM and native shadow only. Synthetic shadow supports form association without the use of ElementInternals
. Components in synthetic shadow must add ARIA attributes and roles explicitly. To create a form with built-in accessibility in synthetic shadow, like for Lightning Experience and Experience Builder sites, we recommend using the base Lightning components.
Input elements inside a native shadow form are hidden inside the shadow DOM. The form can't validate the input elements for submission, so their data isn't included in the FormData
object. Furthermore, form submission fails because the submit event can't escape the shadow boundary.
To include components or elements using native shadow during form submission, use the ElementInternals
Web API and the related Form-Associated Custom Elements (FACE) lifecycle API.
Using ElementInternals
, you can manage a Lightning web component's internal states, such as default Accessible Rich Internet Applications (ARIA) role or ARIA label. You can also configure ElementInternals
to have your component participate in form submissions and validations.
ElementInternals
and the FACE lifecycle API provide several key functionalities.
- Default ARIA semantics-A Lightning web component can have default ARIA attributes and roles even without an explicit ARIA attribute on the host.
- Form association-A Lightning web component can communicate its form-based states and use lifecycle callbacks corresponding to the form. Call
this.attachInternals
to associate anElementInternals
object to your component.
Use ElementInternals
with components that extend LightningElement
only.
ElementInternals
provides a way to allow Lightning web components to fully participate in HTML forms. You can assign the internals to a property and define your ARIA role and attribute values like this.
this.attachInternals()
is available at any point in the component lifecycle, similar to this.template
. However, you can't access internals from outside a component.
this.attachInternals()
can be called once only, and throws an error if called more than once. Avoid calling this.attachInternals()
in a lifecycle hook that can be called multiple times, such as in connectedCallback
or renderedCallback
.
To use the lifecycle callbacks, add a formAssociated
property to identify the element as a form control. These callbacks are optional and lets your element perform something at that point in the lifecycle.
For more information, see web.dev: Form-associated custom elements lifecycle callbacks
To use the component that defines the lifecycle callbacks, nest it within a <form>
tag.
Similar to the behavior of the LWC connectedCallback
lifecycle hook, you can't access formAssociated
or the FACE lifecycle callbacks outside a component.
ElementInternals
is available only with Chromium, Firefox, and Safari.this.attachInternals()
throws an error in unsupported browsers. LWC doesn’t provide a polyfill for unsupported browsers.this.attachInternals
is undefined in server-side rendering.ElementInternals
and the FACE lifecycle callbacks aren't currently serializable as HTML.internals.shadowRoot
doesn't return an instance of theShadowRoot
; it returns the same proxy object asthis.template
. For example,this.template === internals.shadowRoot
returnstrue
.
This example creates a custom form using the <input>
element and implements the validity states for them. The c-control
component contains the <input>
element.
When you click the input field, checkValidity()
displays a custom error if the field is required and nothing is entered.
The CSS appends a red border when the field is in an invalid state.
Next, use the c-control
component within a form
element.
The form
element contains several buttons, which either resets the form, toggles the disabled
property on the input fields, or submits the form.
See Also
- MDN web docs: ElementInternals
- web.dev: Form-associated custom elements