Web components have been able to fully participate in native HTML forms since 2023 — submit their value with FormData, trigger :invalid, reset alongside the <form>, the works. The API that makes it possible, ElementInternals, is now supported in Chromium, Firefox, and Safari 16+.
The catch: nobody tells you it's about 40 lines of repetitive plumbing per component. This post walks through what that plumbing looks like, then shows a small reusable mixin (form-control-mixin) that gets rid of it.
What "form-associated" actually buys you
A form-associated custom element can:
submit a value as part of the form's FormData, under its name attribute






