Skip to content

Field 表单项 ​

把一个控件和它的标签、说明、错误信息排成一组,并替控件接好无障碍关联。 一组相关的表单项用 FieldSet 字段组 包起来,多个表单项之间的间距交给 FieldGroup 表单项分组。

基础用法

标签、控件、说明各放一个插槽。标签自动成为控件的可访问名、说明成为它的描述,点标签聚焦控件。

<pt-field>
  <span slot="label">邮箱</span>
  <pt-input type="email" placeholder="name@example.com"></pt-input>
  <span slot="description">用于登录与找回密码,不会公开</span>
</pt-field>

插槽 ​

插槽放什么
label标签文字。放纯文字的 <span> 即可,字号、字重、颜色由表单项负责
(默认)控件。可以包在容器里(如 pt-input-group),表单项会找到其中第一个控件
description说明文字
error错误信息。有内容时优先于 errors 属性

「控件」指默认插槽里第一个 kit 表单控件:pt-input、pt-textarea、pt-select、pt-native-select、 pt-checkbox、pt-switch、pt-radio-group、pt-slider。嵌套的 pt-field 里的控件归内层所有。 原生 <input> 不在此列 —— 它在 light DOM 里,直接用原生 <label> 更合适。

必填、出错与禁用 ​

必填、出错与禁用

required / invalid / disabled 写在表单项上,会下发给里面的控件:星号、红框、aria-invalid、禁用都跟着走。错误文字放 error 插槽,或用 errors 属性(JS 赋值)。

<pt-field required invalid>
  <span slot="label">用户名</span>
  <pt-input value="a"></pt-input>
  <span slot="error">至少 3 个字符</span>
</pt-field>
<pt-field disabled>
  <span slot="label">账号 ID</span>
  <pt-input value="PT-20260926"></pt-input>
  <span slot="description">创建后不可修改</span>
</pt-field>

required、invalid、disabled 写在表单项上,会经继承通道下发给控件(控件的 inherited-required / inherited-invalid / inherited-disabled attribute):必填星号、红框、aria-invalid / aria-required、表单校验、 禁用都跟着控件自己的实现走,不需要在控件上再写一遍。控件的有效状态是它自己的属性与继承的并集。

表单项不改写控件自己的 required / invalid / disabled:应用在控件上另写的同名属性、受控绑定都与表单项互不干扰, 读到的始终是应用自己写的值;表单项撤回后控件回到它自己的状态。外层 pt-field-set 的 disabled 也走同一条通道, 见 FieldSet 字段组。inherited-* 属于内部通道,不要在应用里直接写。

错误信息有两种给法:

html
<!-- 插槽:任意内容 -->
<pt-field invalid>
  <span slot="label">用户名</span>
  <pt-input></pt-input>
  <span slot="error">至少 3 个字符</span>
</pt-field>
js
// errors 属性:字符串数组,只能用 JS 赋值(React / Vue / Angular 里照常绑定)
field.errors = ['至少 3 个字符', '只能包含字母和数字'];

errors 会去掉空串与重复项:剩一条时显示为纯文本,多条时显示为列表,一条都没有时不渲染。 错误区是 role="alert",出现时读屏会立即念出来。invalid 不会因为有错误信息而自动变真 —— 两者分开写, 便于「先显示提示、提交时才标红」这类时机控制。

排列方向 ​

横向排列

顺序跟随子元素的先后:复选框写在标签前面就排在左侧,开关写在后面就排在右侧,标签与说明那一列撑满剩余宽度。

<pt-field orientation="horizontal">
  <pt-checkbox></pt-checkbox>
  <span slot="label">记住登录状态</span>
</pt-field>
<pt-field orientation="horizontal">
  <span slot="label">邮件通知</span>
  <span slot="description">有新评论时发邮件提醒</span>
  <pt-switch></pt-switch>
</pt-field>
orientation排列
vertical默认。标签、控件、说明、错误上下排列,间距 8px
horizontal标签、说明、错误收成一列,与控件左右排、垂直居中
responsive视口窄于 768px 时同 vertical,宽屏时同 horizontal

顺序跟随子元素在 DOM 里的先后:标签、说明、控件谁写在前面谁就排在前面,错误信息总在最后。 横向时控件写在标签前面(复选框、单选组的常见写法)就排在左侧,写在后面(开关、设置项)就排在右侧。

横向时标签那一列撑满剩余宽度、控件保持自身宽度。要让输入框这类控件撑满,写 pt-field::part(control) { flex: 1; }。

无障碍 ​

  • 标签成为控件的可访问名,说明与错误信息(按这个顺序)成为它的描述。关联经 utils/aria-link 跨过影子边界, 落在控件影子树里真正获得焦点的元素上(与 Label 的 for 同一套机制)。
  • 控件后插入、被替换或移除,标签被移除或改了 slot,文字改了 —— 关联都跟着更新,旧控件上的关联与下发的状态会撤掉。
  • 点标签聚焦控件;pt-checkbox / pt-switch 像原生 label 一样直接切换。点在标签里的链接、按钮与 kit 交互组件(如链接形态的 pt-badge)上、表单项禁用时不转交。 pt-radio-group 没有唯一的聚焦目标,点标签不动(与原生 <legend> 一致)。
  • 标签用带 for 的 pt-label 也可以,点击由它自己转交,表单项不会再切一次。
  • errors 属性渲染在表单项的影子树里,支持 ARIA 元素反射的浏览器也引用不到它(不在控件的祖先树里), 这时靠文字镜像进控件的 aria-description;error 插槽里的元素两条路都走得通。

API ​

属性

属性Attribute类型默认值说明
disableddisabledbooleanfalse禁用:标签与说明变淡,点标签不再聚焦,并下发给控件。外层 pt-field-set 的禁用经 `inherited-disabled` 生效,不改写它
errors—string[] | undefined—错误信息列表(只能用 JS 赋值)。去掉空串与重复项后:一条显示为纯文本,多条显示为列表; 没有内容时不渲染。`error` 插槽有内容时以插槽为准
inheritedDisabledinherited-disabledbooleanfalse外层 pt-field-set 下发的禁用。内部继承通道:由它以 attribute 维护,不建议使用方直接写。 有效禁用是 `disabled` 与它的并集;父元素只写这一条、不碰 `disabled`,读 `el.disabled` 得到的始终是使用方自己写的值
invalidinvalidbooleanfalse出错态:下发给控件(红框、aria-invalid、表单校验失败)。错误文字由 `errors` 或 `error` 插槽给出
orientationorientation"horizontal" | "responsive" | "vertical"'vertical'排列方向。`vertical` 上下排;`horizontal` 标签一列与控件左右排、垂直居中; `responsive` 窄屏(< 768px)上下排、宽屏左右排
requiredrequiredbooleanfalse必填:标签后显示星号,并下发给控件(aria-required、表单校验)

插槽

名称说明
(默认)控件
description说明文字
error错误信息。有内容时优先于 `errors` 属性
label标签文字。放纯文字或 `<span>` 即可,排版由表单项负责

可定制的内部元素(::part())

part说明
base外层排版容器
content标签、说明、错误信息所在的一列(纵向时不成盒,只在横向时是一列)
control控件
description说明
error错误信息(role=alert)
label标签
required必填星号(aria-hidden,必填语义在控件的 aria-required 上)

Apache-2.0 协议开源