-
Notifications
You must be signed in to change notification settings - Fork 798
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
Support formAssociated components (using ElementInternals) #2284
Comments
Are there any plans to implement this any time soon? As OP mentioned, it's already in the spec and is pretty stable at this point. While Chrome and Edge already support it, Firefox is actively working on implementing it (https://bugzilla.mozilla.org/show_bug.cgi?id=1552327). |
Hey all! I'm going to do my research and work on defining what this means to be able to ship. No timeline, but I added a request for comments. If anybody can provide the different use cases or their ideal interface - whether it's a decorator or a modification to a decorator - that would be fantastic! |
Before working out a higher level API I guess we'd need to know whether stencil wants to ship something 'official' that doesn't work cross-browser? Until Safari gets on-board I can see the work to get something working cross-browser being a hot-mess (falling back to a hidden input sprouted to the lightDom / or utilising Perhaps until this feature is cross-browser, stencil should simply not get in way / work out what's disrupting devs using this low-level / native api? |
Having said what I just said ( :D ) ... it looks like there will need to be a hook to get this working with lazy loading - the static property
Then everything works. I'd say the nicest way to implement this would be, via static analysis, to read in whether the user class has |
As noted early, Chromium and Firefox already support the Element Internals API: https://caniuse.com/mdn-api_elementinternals. There is a polyfill for this as well (https://github.com/calebdwilliams/element-internals-polyfill) that could be used with Safari, but it is not small and I have not used it in production. When I tried to get this to work with Stencil a few months back, the main issue was the static Here is a link to the docs on the lifecycle methods: https://web.dev/more-capable-form-controls/#lifecycle-callbacks Here is an example of some of that stuff: get form() { return this.internals_.form; }
get type() { return this.localName; }
get validity() {return this.internals_.validity; }
get validationMessage() {return this.internals_.validationMessage; }
get willValidate() {return this.internals_.willValidate; }
checkValidity() { return this.internals_.checkValidity(); }
reportValidity() {return this.internals_.reportValidity(); } In my experience, we can handle enhancement of the element class in the constructor for adding these properties and lifecycle methods. So as @johnjenkins suggested, the main issue is the static |
Kind of unrelated, but here is the TS decorator I would love to have in Stencil: I imagine it would be a lot of work though and some of this could be done with the decorators that are already provided if they were a little more flexible (synchronous methods and read-only properties for example). |
@splitinfinities we can't use ElementInternals with Stencil field components? Since web components cannot participate in forms are we required to repeat form field code within a Stencil form or is there a way to create reusable field components that work? |
@BenRacicot I'd suggest looking at using |
Hey @johnjenkins thanks for the reply. Unfortunately turning off encapsulation is not an option in my case. |
In order to fully realize this I believe we need to first ship #2899, does that seem to track? Especially for the getters that @nborelli posted above (#2284 (comment)) |
Hi @splitinfinities, we would probably also need a way of adding synchronous methods like the |
Just my own thoughts but I love this idea. A decorator to implement either a decided-solution, or perhaps even the applicable ElementInternals methods to expose field component's attributes to its form's FormData. Perhaps even To have this done for us would be a big win for Stencil IMHO. |
It isn't clear to me that #2889 is required to support |
As a workaround I believe you can temporarily intercept the constructor with a global monkey patch like this. const FORM_ASSOCIATED_ELEMENTS = ['my-input', 'my-select'];
const define = customElements.define;
customElements.define = (name, constructor, options) => {
// This could probably be changed to read a static `formAssociated` field on the associated
// Stencil component class to avoid needing `FORM_ASSOCIATED_ELEMENTS`.
if (FORM_ASSOCIATED_ELEMENTS.includes(name)) {
constructor.formAssociated = true;
}
define(name, constructor, options);
};
defineCustomElements(); // from your loader
delete customElements.define; // revert to the prototype implementation Is there a better way? |
Any update around this 2y discussion? 😁 I saw some libs (like LitElement) already working with form association for some time ago: For now, in my projects I workaround creating a simple input[type=hidden] when a parameter with the name <my-input name="test" form-associated></my-input> // Call in componentDidLoad
private appendInputHidden(): void {
if (this.formAssociated) {
const input = document.createElement('input');
input.name = this.name;
input.id = this.name;
input.value = this.value;
input.type = 'hidden';
this.element.appendChild(input);
}
} and updating the value when the onInput (in the case of input-text) like: private updateInputHidden(value: string = this.value): void {
if (this.formAssociated) {
this.element.querySelector<HTMLInputElement>(`input[name=${this.name}]`).value = value;
}
} But ofc is just a workaround, because now I have more things to manage and "two" inputs (into the DOM and ShadowDOM) My idea/proposal, it will be very interesting to have a property into the @Component({
tag: 'my-input',
styleUrl: 'my-input.scss',
shadow: true,
formAssociated: true // <-- \o/
}) With the flag, the component can inherit the internal behaviors of form association 😋 What you guys think? |
What with Safari getting on-board with this, this feature is now an imperative, so I've just bashed something out very quickly in order to get the ball rolling. #3519 - essentially does what I mentioned above - reads in
If people have strong feelings I can look at that instead - lemme know. Regarding 'readonly' props - I suspect this one needs to be merged But both these issues can be worked around for now (as mentioned) by using constructor to add these properties and methods. |
Tks @johnjenkins Well, about use inside of the I really understand the argument and I like it:
However, stencil defined some rules and use a static property looks a "rule breaker" But maybe it's about the plans of Stencil and how much effort will be expended in the future to keep alive 💪 So, if the plan is more aligned in have less I'm glad in in see this important issue walking, hope I helped in think about it |
Any update on this? |
Any updates here? |
https://webkit.org/blog/13703/release-notes-for-safari-technology-preview-162/ Element Internals just dropped in Safari Tech Preview. |
Any update on this? |
Please add this feature :) |
Any update on this? |
Any update? This would be really great since we cannot use shadow dom in a reasonable way without it |
We are using web components built with stenciljs in a react application. Because this feature is not available, we are forced to create controlled component instead of a an uncontrolled one. As this issue is open for over 3 year's and requested by many developer, I kindly request the maintainers to add this feature |
In our case, we've been forced to opt Lit only for form elements (we much prefer keep working with stencil), this is very time consuming for us and we still hope this feature will be implemented as soon as possibile. Please let us know if at least there is an intention to integrate this feature. |
Just adding to this request to get some visibility. |
+1 anything new regarding the issue? |
👋 ElementInternals are the next "thing" for us to investigate support for Stencil. While I don't have any timeline, it is the next Web Component ecosystem feature that we have our sights set on! |
Just learned about ElementInternals which would solve a big issue in our design-system. Would be cool to see this working for StencilJS :) |
This adds support for building form-associated custom elements in Stencil components, allowing Stencil components to participate in HTML forms in a rich manner. This is a popular request in the Stencil community (see #2284). A minimal Stencil component that uses the new APIs to integrate with a form could look like this: ```tsx import { Component, h, AttachInternals } from '@stencil/core'; @component({ tag: 'my-component', styleUrl: 'my-component.css', shadow: true, formAssociated: true }) export class MyComponent { @AttachInternals() internals: ElementInternals; render() { return <div>Hello, World!</div>; } } ``` The new form-association technology is exposed to the - A new option called `formAssociated` has been added to the [`ComponentOptions`](https://github.com/ionic-team/stencil/blob/06f6fad174c32b270ce239afab5002c23d30ccbc/src/declarations/stencil-public-runtime.ts#L10-L55) interface. - A new `@AttachInternals()` decorator can be used to indicate a property on a Stencil component to which an [`ElementInternals`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals) object will be bound at runtime. - Using `@AttachInternals()` is supported both for lazy builds ([`www`](https://stenciljs.com/docs/www), [`dist`](https://stenciljs.com/docs/distribution)) as well as for [`dist-custom-elements`](https://stenciljs.com/docs/custom-elements). The new behavior is implemented at compile-time, and so should result in only very minimal increases in code / bundle size. Support exists for using form-associated components in both the lazy and the CE output targets, as well as some extremely minimal provisions for testing. Documentation for this feature was added to the Stencil site here: stenciljs/site#1247
This adds support for building form-associated custom elements in Stencil components, allowing Stencil components to participate in HTML forms in a rich manner. This is a popular request in the Stencil community (see #2284). A minimal Stencil component that uses the new APIs to integrate with a form could look like this: ```tsx import { Component, h, AttachInternals } from '@stencil/core'; \@component({ tag: 'my-component', styleUrl: 'my-component.css', shadow: true, formAssociated: true }) export class MyComponent { @AttachInternals() internals: ElementInternals; render() { return <div>Hello, World!</div>; } } ``` The new form-association technology is exposed to the - A new option called `formAssociated` has been added to the [`ComponentOptions`](https://github.com/ionic-team/stencil/blob/06f6fad174c32b270ce239afab5002c23d30ccbc/src/declarations/stencil-public-runtime.ts#L10-L55) interface. - A new `@AttachInternals()` decorator can be used to indicate a property on a Stencil component to which an [`ElementInternals`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals) object will be bound at runtime. - Using `@AttachInternals()` is supported both for lazy builds ([`www`](https://stenciljs.com/docs/www), [`dist`](https://stenciljs.com/docs/distribution)) as well as for [`dist-custom-elements`](https://stenciljs.com/docs/custom-elements). The new behavior is implemented at compile-time, and so should result in only very minimal increases in code / bundle size. Support exists for using form-associated components in both the lazy and the CE output targets, as well as some extremely minimal provisions for testing. Documentation for this feature was added to the Stencil site here: stenciljs/site#1247
This adds support for building form-associated custom elements in Stencil components, allowing Stencil components to participate in HTML forms in a rich manner. This is a popular request in the Stencil community (see #2284). The new form-association technology is exposed to the component author via the following changes: - A new option called `formAssociated` has been added to the [`ComponentOptions`](https://github.com/ionic-team/stencil/blob/06f6fad174c32b270ce239afab5002c23d30ccbc/src/declarations/stencil-public-runtime.ts#L10-L55) interface. - A new `@AttachInternals()` decorator can be used to indicate a property on a Stencil component to which an [`ElementInternals`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals) object will be bound at runtime. - Using `@AttachInternals()` is supported both for lazy builds ([`www`](https://stenciljs.com/docs/www), [`dist`](https://stenciljs.com/docs/distribution)) as well as for [`dist-custom-elements`](https://stenciljs.com/docs/custom-elements). The new behavior is implemented at compile-time, and so should result in only very minimal increases in code / bundle size. Support exists for using form-associated components in both the lazy and the CE output targets, as well as some extremely minimal provisions for testing. Documentation for this feature was added to the Stencil site here: stenciljs/site#1247
) This adds support for building form-associated custom elements in Stencil components, allowing Stencil components to participate in HTML forms in a rich manner. This is a popular request in the Stencil community (see #2284). The new form-association technology is exposed to the component author via the following changes: - A new option called `formAssociated` has been added to the [`ComponentOptions`](https://github.com/ionic-team/stencil/blob/06f6fad174c32b270ce239afab5002c23d30ccbc/src/declarations/stencil-public-runtime.ts#L10-L55) interface. - A new `@AttachInternals()` decorator can be used to indicate a property on a Stencil component to which an [`ElementInternals`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals) object will be bound at runtime. - Using `@AttachInternals()` is supported both for lazy builds ([`www`](https://stenciljs.com/docs/www), [`dist`](https://stenciljs.com/docs/distribution)) as well as for [`dist-custom-elements`](https://stenciljs.com/docs/custom-elements). The new behavior is implemented at compile-time, and so should result in only very minimal increases in code / bundle size. Support exists for using form-associated components in both the lazy and the CE output targets, as well as some extremely minimal provisions for testing. Documentation for this feature was added to the Stencil site here: stenciljs/site#1247
Hey all! 👋 We're excited to say that initial support for Form Associated Custom Elements (FACE) was included as a part of today's v4.5.0 release! Please open a new issue if you encounter any problems! |
the problem is this new decorator fails in older safari version and break the rendering. TypeError: e.$hostElement$.attachInternals is not a function. (In 'e.$hostElement$.attachInternals()', 'e.$hostElement$.attachInternals' is undefined) Here a screenshot out of the browsers firefox vs safari in chromatic: |
@dutscher At this time, Stencil does not polyfill ElementInternals-related functions, such as
|
Stencil version:
I'm submitting a:
[ ] bug report
[x] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/
Current behavior:
Stencil component with a static
formAssociated
property does not behave like a vanilla customElement, accessing form relatedinternals
methods throws "DOMException: Failed to read the 'form' property from 'ElementInternals': The target element is not a form-associated custom element." in chrome.Expected behavior:
The static property formAssociated defined on a component should be attached to proxy class defining the customElement or at least Stencil could provide an idiomatic way to allow to attach static properties. It would be awesome to enventually provide a shim for unsuporting browser... but this may deserve it's own issue ;)
Steps to reproduce:
A click on the below component (when nested in a form) should submit the form and not throw an error on chrome.
Related code:
Other information:
More about formAssociated elements use cases: https://web.dev/more-capable-form-controls/
Specifications of formAssociated elements: https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-face-example
A blog post about form related component with stencil \o/
https://www.hjorthhansen.dev/shadow-dom-form-participation/ , but formAssociated example seems to be pseudo code (not working) :/
Info about browser support https://www.chromestatus.com/feature/4708990554472448
The text was updated successfully, but these errors were encountered: