A form-associated custom element can participate in form submission through ElementInternals.
HTML form-associated custom elements: join the form contract deliberately
When the element earns its place
A dispatch system has a reusable priority picker that existing native controls cannot express well. The host below names the field and sits inside a form, but its JavaScript class must declare formAssociated, attach internals, and call setFormValue whenever the choice changes. Without that implementation, the visible custom element contributes no value to submission. Start with a native select unless the interaction and its accessibility behavior justify owning the extra code.
<form action="/dispatch/priority" method="post">
<label for="dispatch-priority">Dispatch priority</label>
<dispatch-priority id="dispatch-priority" name="priority"></dispatch-priority>
<button type="submit">Save priority</button>
</form>
<script type="module">
class DispatchPriority extends HTMLElement {
static formAssociated = true;
constructor() {
super();
this.internals = this.attachInternals();
this.internals.setFormValue("standard");
}
}
customElements.define("dispatch-priority", DispatchPriority);
</script>Behavior boundary
The sample establishes submission wiring only; it does not draw an interactive picker. A production component needs its own keyboard behavior, accessible value, validation, reset, disabled state, and choice-update path before it can replace a select.
Cost and operational limits
The custom class adds script and testing cost. Native select provides value submission and keyboard behavior without that code, so compare the required interaction against the maintenance burden before choosing a custom control.
Common Mistakes
- Do not assume a custom tag submits its name automatically.
- Do not ship this wiring sample as a finished picker.
- Do not skip reset, disabled, and assistive-technology tests.
