-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add form-associated custom elements content #42
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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", | ||
|
@@ -199,51 +203,154 @@ <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> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a Mozilla stance link we could use? And should we link to chromestatus.com as well? Even when “shipped”. |
||
<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> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, they’re here 😳 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this the wrong place for that info? |
||
<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> | ||
<a href="https://github.com/WebKit/standards-positions/issues/47#issuecomment-1221419927">WebKit is in favor and has the feature in active development</a> and has <a href="https://github.com/WebKit/WebKit/pull/2690">merged a PR implementing the first part of <code>ElementInternals</code></a> which includes the form-associated custom elements behavior; however, the initial PR doesn't include the actual form-association APIs. | ||
</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> | ||
</section> | ||
<section> | ||
<h3>Concerns</h3> | ||
<ul> | ||
<li>---</li> | ||
<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>Dissenting Opinion</h3> | ||
<h3>Concerns</h3> | ||
<ul> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might toss the whole section if there’s no dissension? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. |
||
<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>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> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we think we need / want a dedicated link to the issue instead of a repo? Just curious if that would be helpful from reader perspective? Or we also add this link in here at the top for reference?
https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-face-example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I wrestled with that. Unfortunately there seem to be a number of separate issues since this really is a collection of features/APIs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’d say a perponderance of links are better than a dearth. It could allow us to draw a fine line as to what does 2022 support look like down the line. However, I don’t see it specifically blocking this pass at the data!