Element Internals API

Element Internals API представляет собой механизм, позволяющий создавать и управлять внутренними аспектами веб-компонентов, которые обычно недоступны извне. Этот API обеспечивает расширенные возможности для работы с состоянием компонента, формами и доступностью, сохраняя при этом инкапсуляцию.


Подключение Element Internals

Для использования Element Internals внутри компонента Stencil необходимо создать приватное свойство типа ElementInternals. Обычно это делается в классе компонента через декоратор @Component и хук @Element:

import { Component, Element, h } from '@stencil/core';

@Component({
  tag: 'my-element',
  shadow: true
})
export class MyElement {
  @Element() el!: HTMLElement;
  private internals!: ElementInternals;

  connectedCallback() {
    this.internals = this.el.attachInternals();
  }

  render() {
    return <div>Контент компонента</div>;
  }
}

Ключевой момент: метод attachInternals() возвращает объект ElementInternals, через который реализуются расширенные возможности компонента.


Работа с формами

Element Internals позволяет компоненту взаимодействовать с формами так, как если бы он был обычным <input> или <select>. Основные возможности:

  • Состояние формы (setFormValue): задает значение компонента, которое будет отправлено при сабмите формы.
  • Валидация (setValidity): устанавливает состояние валидности и сообщения об ошибке.
  • Доступ к родительской форме (form): получение ссылки на <form>, в которой находится компонент.

Пример интеграции с формой:

connectedCallback() {
  this.internals = this.el.attachInternals();
  this.internals.setFormValue('initial value');
}

handleInputChange(value: string) {
  this.internals.setFormValue(value);
}

validateInput(isValid: boolean) {
  if (isValid) {
    this.internals.setValidity({});
  } else {
    this.internals.setValidity({ customError: true }, 'Некорректное значение');
  }
}

Особенность: компонент может участвовать в механизме отправки формы и показывать собственные ошибки валидации без использования стандартных <input> элементов.


Управление состоянием доступности

Element Internals интегрируется с ARIA и предоставляет возможность управлять состоянием доступности:

  • role: через internals.role можно указать роль компонента для скринридеров.
  • aria-* атрибуты: управляются через стандартные методы DOM.
  • shadow DOM и доступность: internals учитывает shadow DOM, что позволяет правильно формировать tree доступности.

Пример установки роли и aria-меток:

connectedCallback() {
  this.internals = this.el.attachInternals();
  this.internals.role = 'checkbox';
  this.internals.ariaChecked = 'false';
}

toggleCheck() {
  const checked = this.internals.ariaChecked === 'true';
  this.internals.ariaChecked = (!checked).toString();
}

Псевдоклассы состояния

Element Internals предоставляет возможность работать с псевдоклассами CSS, такими как :hover, :focus, а также с формой:

  • internals.states — набор состояний, который можно использовать для стилизации через CSS.
  • Поддержка состояния :valid и :invalid для кастомных элементов.

Пример установки состояния валидности:

checkValidity() {
  const isValid = this.someValidationLogic();
  this.internals.states.add(isValid ? 'valid' : 'invalid');
}

Это позволяет использовать стандартные селекторы CSS для визуального отображения состояния компонента.


Поддержка shadow DOM

Element Internals корректно работает с shadow DOM, что обеспечивает инкапсуляцию стилей и DOM-структуры компонента, сохраняя при этом интеграцию с формами и системой доступности:

  • Shadow DOM не мешает родительской форме получать значения компонента.
  • Атрибуты доступности корректно транслируются скринридерами, даже если компонент полностью изолирован.

Особенности совместимости

  • Поддержка Element Internals ограничена современными браузерами (Chrome, Edge, Opera, Safari). Для Firefox требуется использование полифила.
  • Не все функции работают без shadow DOM. Для полного использования API рекомендуется включать shadow DOM при создании компонента.

Практические рекомендации

  1. Использовать Element Internals для кастомных формовых элементов.
  2. Управлять состояниями и валидностью через setValidity и setFormValue.
  3. Устанавливать роли и aria-метки для правильной доступности.
  4. Поддерживать shadow DOM для инкапсуляции и совместимости с internals.
  5. Проверять браузерную поддержку и использовать полифилы при необходимости.

Использование Element Internals в Stencil обеспечивает создание полностью интегрированных и доступных веб-компонентов, расширяя возможности стандартного DOM и формы, сохраняя при этом инкапсуляцию и удобство управления состояниями.