Skip to content

Commit

Permalink
keep fleshing that out
Browse files Browse the repository at this point in the history
  • Loading branch information
alicewriteswrongs committed Oct 9, 2023
1 parent e1ce01e commit 526c523
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 6 deletions.
30 changes: 30 additions & 0 deletions docs/components/component.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,36 @@ In the example above, the following allows `todo-list` to display the provided a

For more information on configuring assets, please see Stencil's [Assets Guide](../guides/assets.md)


### `formAssociated`

**Optional**

If `true` the component will be
[form-associated](https://html.spec.whatwg.org/dev/custom-elements.html#form-associated-custom-element),
allowing you to take advantage of the
[`ElementInternals`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals)
API to enable your Stencil component to participate in forms.

A minimal form-associated Stencil component could look like this:

```tsx
import { Component } from '@stencil/core';

@Component({
tag: 'form-associated',
formAssociated: true
})
export class FormAssociated {
render() {
return <span>form associated!</span>
}
}
```

See the documentation for [form-associated components](./form-associated.md)
for more info and examples.

### scoped

**Optional**
Expand Down
34 changes: 28 additions & 6 deletions docs/components/form-associated.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ and presentation.
:::caution
Browser support for the APIs that this feature depends on is still relatively
low ([~84% as of this writing](https://caniuse.com/?search=attachInternals))
and the Stencil team does not plan to officially support or incorporate any
and the Stencil team has no plans at present support or incorporate any
polyfills for the browser functionality. Accordingly, this is a 'use at your
own risk' feature: it is up to you as a developer to ensure the browsers you
need to support have shipped the necessary APIs.
Expand Down Expand Up @@ -47,15 +47,26 @@ In order to meaningfully interact with a `<form>` element that is an ancestor
of our custom element we'll need to get access to an
[`ElementInternals`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
object corresponding to our element instance. Stencil provides a decorator,
`@FormInternals`, which does just this, allowing you to decorate a property on
`@AttachInternals`, which does just this, allowing you to decorate a property on
your component and bind an `ElementInternals` object to that property which you
can then use to interact with the surrounding form.

A minimal Stencil component using this API to implement a custom text input
could look like this:
:::info
Under the hood the `AttachInternals` decorator makes use of the very similarly
named
[`attachInternals`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals)
method on `HTMLElement` to associate your Stencil component with an ancestor
`<form>` element. During compilation, Stencil will generate code that calls
this method at an appropriate point in the component lifecycle for both
[lazy](../output-targets/dist.md) and [custom
elements](../output-targets/custom-elements.md) builds.
:::

A Stencil component using this API to implement a custom text input could look
like this:

```tsx title="src/components/custom-text-input.tsx"
import { Component, h, FormInternals, State } from '@stencil/core';
import { Component, h, AttachInternals, State } from '@stencil/core';

@Component({
tag: 'custom-text-input',
Expand All @@ -65,7 +76,7 @@ import { Component, h, FormInternals, State } from '@stencil/core';
export class CustomTextInput {
@State() value: string;

@FormInternals() internals: ElementInternals;
@AttachInternals() internals: ElementInternals;

handleChange(event) {
this.value = event.target.value;
Expand All @@ -87,3 +98,14 @@ export class CustomTextInput {
}
}
```

This component doesn't do a whole lot as-is, but luckily a great deal more is
possible with the `ElementInternals` API, including [setting the element's
validity](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setValidity),
reading the validity state of the form, reading other form values, and more.

### Resources

- [whatwg specification for form-associated custom elements](https://html.spec.whatwg.org/dev/custom-elements.html#form-associated-custom-elements)
- [ElementInternals and Form-Associated Custom Elements](https://webkit.org/blog/13711/elementinternals-and-form-associated-custom-elements/) from the WebKit blog
-

0 comments on commit 526c523

Please sign in to comment.