Skip to main content
Version: v5 (Preview)

Attach Internals Decorator

The @AttachInternals decorator is used to attach ElementInternals to a Stencil component. This allows you to leverage features such as Custom States and Form Association.

Form Association​

Decorating a property with @AttachInternals() automatically marks the component as form-associated — there's no separate formAssociated option on @Component(). To attach ElementInternals for something like Custom States without form association, use @AttachInternals({ formAssociated: false }).

Read the dedicated guide on Form Associated Components and how to use @AttachInternals there.

Note that ElementInternals on a closed shadow root (encapsulation: { type: 'shadow', mode: 'closed' }) is still accessible via @AttachInternals() from inside the component — closed mode only prevents access to shadowRoot from outside the component.

Custom States​

You can use the @AttachInternals decorator to define Custom States for your component.

import { Component, AttachInternals } from '@stencil/core';
/**
* My Element component
*/
@Component({
tag: 'my-element',
styleUrl: 'my-element.css',
encapsulation: { type: 'shadow' },
})
export class MyElement {
@AttachInternals({
states: {
/** A custom state for my element */
'my-custom-state': true,
/** Another custom state for my element */
'another-state': false
}
}) internals: ElementInternals;
render() {
return <div>My Element</div>;
}
}

In the example above, we define two custom states: my-custom-state and another-state.

The initial values of the custom states can be set via the states object and later on, you can update the states dynamically using the internals.states property. For example:

handleClick() {
this.internals.states.add('another-state'); // to add a state
this.internals.states.delete('my-custom-state'); // to remove a state
}

You or your element users can then use custom states in CSS. Use them internally, in the component's stylesheet, or externally, from the page. Click the element below to run handleClick():

my-element.css
:host(:state(my-custom-state)) {
background-color: yellow;
}
index.html
<style>
my-element:state(another-state) {
border: 2px solid red;
}
</style>

<script type="module" src="./my-element.js"></script>

<my-element></my-element>