Skip to content

Commit

Permalink
feat: add form-associated custom elements content
Browse files Browse the repository at this point in the history
  • Loading branch information
calebdwilliams authored and Westbrook committed Aug 25, 2022
1 parent 77711f8 commit 6319ecb
Showing 1 changed file with 122 additions and 12 deletions.
134 changes: 122 additions & 12 deletions reports/2022.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
name: "Alan Dávalos",
url: "https://github.com/alangdm",
},
{
name: "Caleb Williams",
url: "https://github.com/calebdwilliams"
}
],
github: "w3c/webcomponents-cg",
shortName: "webcomponents-cg",
Expand Down Expand Up @@ -199,51 +203,157 @@ <h3>Links</h3>
<dt>Previous WCCG Report(s)</dt>
<dd><a href="https://w3c.github.io/webcomponents-cg/index.html#form-associated-custom-elements">2021</a></dd>
<dt>GitHub issues:</dt>
<dd>---</dd>
<dd><a href="https://github.com/whatwg/html/issues">https://github.com/whatwg/html/issues</a></dd>
<dt>Browser positions:</dt>
<dd>---</dd>
<dd>
<ul>
<li>
<a href="https://github.com/WebKit/standards-positions/issues/47">WebKit</a>
</li>
</ul>
</dd>
</dl>
</section>
<section>
<h3>Description</h3>
<p>---</p>
<p>The form-associated custom elements APIs enable custom elements to participate in form submission and validation lifecycles.</p>
</section>
<section>
<h3>Status</h3>
<ul>
<li>---</li>
<li>
<a href="https://chromestatus.com/feature/4708990554472448">Chrome/Edge (shipped in version 77)</a>
</li>
<li>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setFormValue">Firefox (shipped in version 90)</a>
</li>
<li>
Safari has <a href="https://github.com/WebKit/WebKit/pull/2690">merged a PR implementing the first part of the ElementInternals spec</a> which includes the form-associated custom elements behavior; however, the initial PR doesn't include the actual form-association APIs. The polyfill does check for the presence of the form-associated APIs separately from ElementInternals, so this is not likely to cause any issues if it is released in part.
</li>
</ul>
</section>
<section>
<h3>Initial API Summary/Quick API Proposal</h3>
<p>Summary or proposal based on current status; paragraph(s) and code.</p>
<p>The form-associated custom elements APIs are implemented within the attachInternals method on the HTMLElement prototype. Calling attachInternals returns an instance of an ElementInternals object which grants developers the ability to interact with form elements provided they designate their element as a form-associated element.</p>
<pre>
<code>
%gt;form>
%gt;fancy-input name="fancy">%gt;/fancy-input>
%gt;/form>

%gt;script>
class FancyInput extends HTMLElement {
static get formAssociated() {
return true;
}

constructor() {
super();
this.#internals = this.attachInternals();
this.#internals.setFormValue('I can participate in a form!');
}
}

customElements.define('fancy-input', FancyInput);

document.querySelector('form').addEventListener('submit', event => {
event.preventDefault();
const formData = new FormData(event.target);

console.log(formData.get('fancy')); // logs 'I can participate in a form!'
});
%gt;/script>
</code>
</pre>
<p>The <code>setFormValue</code> method can accept several types of data including strings, <code>FileData</code> and <code>FormData</code> objects, the latter of which can allow a nested form to participate with a parent in its entirety.</p>
<p>In addition to providing an method for adding a value to a form object, the form-associated APIs provide a surface to allow custom elements to participate in form validation.</p>
<pre>
<code>
class FancyInput extends HTMLElement {
static get formAssociated() {
return true;
}

constructor() {
super();
const root = this.attachShadow({ mode: 'open' });
this.#internals = this.attachInternals();
this.#internals.setFormValue('I can participate in a form!');
const button = document.createElement('button');
root.append(button);

button.addEventListener('click', this.#onClick);
this.button = button;
}

#onClick = () => {
if (this.#internals.invalid) {
this.#internals.setValidity(); // Marks the element as valid
} else {
this.#internals.setValidity({
customError: true
}, 'You must click the button', this.button); // Marks the element as invalid and will focus on the button when the form checks validity
}
}
</code>
</pre>
</section>
<section>
<h3>Key Scenarios</h3>
<p>---</p>
<ul>
<li>Enable custom elements to participate in form submission by adding a value to the <code>FormData</code> object, adding to the <code>HTMLFormElement.prototype.elements</code> object and in other submission formats.</li>
<li>Enables custom elements to participate in the form validation lifecycle by providing APIs similar to and building on top of the constraint validation APIs.</li>
</ul>
</section>
<section>
<h3>Concerns</h3>
<ul>
<li>---</li>
<li><a href="https://github.com/whatwg/html/issues/5891">HTMLFormElement elements does not contain form-associated CustomElements when name attribute is shared</a></li>
<li>The form-associated APIs currently have <a href="https://github.com/WICG/webcomponents/issues/814">no way for a developer to behave as a custom submit button</a>. Though there are <a href="https://twitter.com/justinfagnani/status/1510387984830386180">several</a> <a href="https://github.com/open-wc/form-participation/tree/main/packages/form-helpers#implicit-form-submit">workarounds</a>.</li>
</ul>
</section>
<section>
<h3>Dissenting Opinion</h3>
<ul>
<li>---</li>
</ul>
</section>
<section>
<h3>Related Specs</h3>
<ul>
<li>---</li>
<li>
<code>CustomStateSet</code>
<ul>
<li>
<a href="https://wicg.github.io/custom-state-pseudo-class/#customstateset">Specification</a>
</li>
<li>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet">
<abbr title="Mozilla Developer Network">MDN</abbr>
</a>
</li>
</ul>
</li>
<li>
<a href="https://wicg.github.io/aom/explainer.html#default-semantics-for-custom-elements-via-the-elementinternals-object">
AriaMixin/accessibility object model
</a>
</li>
</ul>
</section>
<section>
<h3>Open Questions</h3>
<ul>
<li>---</li>
<li>
It is currently unclear how form-associated custom elements should participate in the autocomplete lifecycle despite there being an API for that purpose. It is currently unclear per the spec how this behavior should work. Currently Chromium implements code for the <code>formStateRestoreCallback</code> callback only for restore events (such as back button or page refresh), but does not call the custom element reaction for autocomplete. Firefox currently does not ship any code referencing the <code>formStateRestoreCallback</code>.
<ul>
<li>
<a href="https://github.com/whatwg/html/issues/7292">Form restoration interop</a>
</li>
<li>
<a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1335202">
Chromimum Issue 1335202: formStateRestoreCallback custom element reaction will not be called for 'autocomplete'
</a>
</li>
</ul>
</li>
</ul>
</section>
</section>
Expand Down

0 comments on commit 6319ecb

Please sign in to comment.