[TPAC Prep] Form Associated Custom Elements #69
Replies: 2 comments 2 replies
-
@ryanbethel awesome summary! One other thing (sorry, these keep popping in my head) is "custom states". So if you have a FACE and you want to indicate state similar to However, this is not standardised across all browsers yet. There has been discussion in WebKit if the CSS part if the best way forward. One alternative is This may be worth adding under "concerns" as well. The current best practice afaik is to "reflect" properties as attributes on the host element. But for certain attributes this can cause problems. |
Beta Was this translation helpful? Give feedback.
-
Would you consider FACE as a feature of ElementInternals in a way that this should be renamed "Element Internals"? If there true, then we could have some sections based on things like:
|
Beta Was this translation helpful? Give feedback.
-
Form Associated Custom Elements: Current Status and Alternatives
<my-input>
,<custom-range-selector>
elementInternals
elementInternals
Overview
Form Associated Custom Elements are primarily associated with the ElementInternals specification. Chrome and Safari have fully implemented
ElementInternals
. Firefox has the value and validation but has not implemented most of the ARIA and role properties.This document addresses some additional challenges with forms not covered in ElementInternals.
Use cases
1. Creating custom elements to act as form controls
The Form Associated Custom Elements API can be used to create new elements that contribute to form submission without any underlying form controls.
Example:
2. Composing form control elements in a custom element wrapper
The FACE API’s can also be used to create a custom element composed of form controls like
<input>
etc. Even if a user would like to include a checkbox in a custom element and maintain all its normal form behavior, it must be reimplemented with element internals. There is no way to leverage this built-in behavior.Example:
Recent Changes
requestSubmit()
has shipped for all major browsers making custom element submit button easier. A custom element can callElementInternals.form.requestSubmit()
. Proposals for a full solution are discussed in the problems section below.name
bug: reported in previous report has been fixed (HTMLFormElement elements does not contain form-associated CustomElements when name attribute is shared whatwg/html#5891)Form Behaviors
The following is a partial list of the behaviors to consider when creating a custom element for a form.
ElementInternals.setFormValue()
ElementInternals.setValidity()
…eventListener
callsmyForm.requestSubmit()
eventListeners('keypress',...)
->myForm.requestSubmit()
attachShadowroot({mode: 'open', delegatesFocus: true})
formStateRestoreCallback()
formResetCallback()
ElementInternals.role
,.ariaChecked
, …Problems/Concerns
Requires a lot of code: A common use case for FACE is to wrap an existing form control to extend behavior in some way. For instance to package a checkbox or text input and add a label to it requires a lot of boilerplate to add back the existing behavior of a checkbox.
Nesting controls in shadow DOM: A nested form in a custom element can set multiple values by using
FormData
and handle validation. But having any intermediate shadow DOM causes problems. The intermediate custom element would need to have a form element to consolidate the contained forms inputs back into FormData and then that object could be passed on. Otherwise, the inputs would have to be handled and passed with ElementInternals individually. Here is a codepen demonstrating this issue (https://codepen.io/rbethel/pen/jOQdmxY)Slotting native form controls: Slotting native form controls into custom elements leaves the light DOM controls active in the form. For example:
<my-input><input required></my-input>
causes unexpected behavior where the light DOM input and the custom element input are both active. Here is a codepen demonstrating the issue (https://codepen.io/rbethel/pen/KKrJmRQ)Label Association: It is difficult without workarounds to associate a label with an input inside the Shadow DOM. One solution is to leave the leave the input in the Light DOM as discussed above by slotting it in. (i.e.
<label for="firstname">First Name</label><my-input><input id="firstname"></my-input>
). This solves the label association but has other downsides discussed above and it may not be the preferred way to structure the Custom Element. The Element Handles proposal may help solve this problem (https://github.com/behowell/aom/blob/element-handles-explainer/element-handles-explainer.md).CE as submit button: As noted in recent changes the addition of
requestSubmit()
shipping to all browsers makes this much easier. Implicit submit is still not handled well. The proposal (Form-associated custom elements: being a submit button WICG/webcomponents#814) to addthis.#internals.submitButton = true
seems to solve most use cases.Firefox properties not implemented yet: They do not support role, and aria properties.
(https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals#browser_compatibility)
User Recommendations
Creating Form Associated Custom Elements with the Shadow DOM and ElementInternals requires properly handling dozens of behaviors that application developers normally get for free with HTML. This is often not apparent from simple examples where only
setFormValue()
is shown. This specification is a valuable tool for library authors and people building design systems. But partial implementation leaves inaccessible forms. Below is a minimal example of a checkbox with and without the shadowDOM. It takes roughly 80 lines of code to put back most of the behavior the Shadow DOM breaks. Here is a codepen with this example https://codepen.io/rbethel/pen/zYMeZEd.References/Resources
Beta Was this translation helpful? Give feedback.
All reactions