通过 ElementInternals 与表单控件关联的自定义标签元素?

问题描述 投票:0回答:1

我正在编写一个名为

fancy-input
的自定义输入元素,它可以通过
FormInternals
API 参与表单。特别是,
ElementInternals.labels
属性为我提供了通过其
label
属性关联到
for
实例的
fancy-input
元素列表。

但是现在假设我还想编写一个名为 fancy-label 的自定义

label
元素。它在其影子 DOM 中以奇特的样式、格式等渲染原生标签元素。如何让它知道
fancy-label
的实例是与
fancy-input
实例关联的“标签”。特别是,我希望我的
fancy-label
节点出现在通过在关联的
NodeList
元素上调用
ElementInternals.labels
返回的
fancy-input
中。

一种可能的方法是让

fancy-label
将原生
label
渲染到插槽中,将其保留在 light DOM 中,因此对表单和
fancy-input
元素可见。但是有没有办法在
label
的影子 DOM 中使用原生
fancy-label
呢?

forms web-component shadow-dom custom-element lit-element
1个回答
0
投票

当今与表单关联元素 (FACE) 相关的 API 不允许您创建像本机

label
一样功能的自定义标签。这个话题已经去年讨论过,可以通过委托标签跨 DOM 引用来解决。但是,您今天仍然可以相当轻松地实现可用的自定义标签。可行性将取决于您的目标。

例如,代替这个要求:

“我希望我的

fancy-label
节点出现在通过在关联的 fancy-input 元素上调用
NodeList
返回的
ElementInternals.labels
中。”

这么说吧:

“我希望我的

fancy-label
节点能够像本机
label
一样使用鼠标、键盘和屏幕阅读器 (SR) 等辅助技术。”

此要求可以通过

aria-labelledby
属性来实现。您可以让字段指向其标签,而不是让标签指向其字段。您需要为标签而不是字段分配唯一的 ID:

<fancy-label id="text-label">
  Disabled pc-checkbox:
  <input name="text" type="text" aria-labelledby="text-label">
</fancy-label>

<fancy-label id="text-label">Disabled pc-checkbox:</fancy-label>
<input name="text" type="text" aria-labelledby="text-label">

您可以通过

aria-labelledby
引用任何有内容的元素。 SR 将像读取本机内容一样读取其内容
label
。剩下的就是处理自定义标签上的点击,以便他们在字段上执行点击。你需要一点 JavaScript 来完成它:

class FancyLabel extends HTMLElement {
  constructor() {
    super()

    this.attachShadow({ mode: 'open' })
    this.shadowRoot.appendChild(document.createElement('slot'))

    this.addEventListener('click', event => this.#handleClick(event))
  }

  #handleClick(event) {
    const field = document.querySelector(`[aria-labelledby="${this.id}"]`)
    // ignore the click if the field does not exist, or if it is disabled,
    // or if the field is inside the label and this event bubbled from it
    if (!field || field.disabled || event.target === field) return
    field.focus()
    field.click()
  }
}

customElements.define('fancy-label', FancyLabel)
© www.soinside.com 2019 - 2024. All rights reserved.