mcpField
S
sgds-forms

sgds-forms

github.com/govtechsg开发18245 次安装2 天前更新
代码仓库

关于 sgds-forms

sgds-forms 介绍 SGDS 表单组件的验证模式,这些组件可融入浏览器原生表单行为。它帮助开发者处理内置约束、错误反馈、提交数据和自定义验证逻辑。

主要功能

  1. 01原生表单提交与 FormData
  2. 02内置约束验证
  3. 03可配置的验证反馈
  4. 04按组件或整个表单控制验证
  5. 05使用 setInvalid 自定义验证

适用场景

  1. 01字段无效时阻止表单提交
  2. 02显示浏览器或自定义验证消息
  3. 03将 SGDS 字段接入第三方验证

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/govtechsg/sgds-web-component --skill sgds-forms

安装后在 Claude Code 中输入/sgds-forms确认已加载。

详细介绍

SGDS 表单验证模式

SGDS 表单组件集成了浏览器的 ElementInternals API,因此其行为与原生 HTML 表单控件一致——它们会自动参与 <form> 提交、FormData 和约束验证。

前提条件

安装和框架集成说明请参阅 sgds-components。

所有表单组件都必须放在 <form> 元素内,并设置 name 属性,才能参与表单提交。

快速决策指南

显示原生 HTML 验证消息? → 为每个表单组件添加 hasFeedback

字段无效时阻止提交? → 内置功能,无需额外代码

读取已提交的字段值? → 在提交处理程序中使用 new FormData(event.target)

针对单个组件禁用 SGDS 验证? → 在 <sgds-input>、<sgds-textarea>、<sgds-combo-box>、<sgds-select>、<sgds-datepicker>、<sgds-quantity-toggle> 或 <sgds-file-upload> 上使用 noValidate 属性

针对整个表单禁用 SGDS 验证? → 在 <form> 元素上设置 novalidate

运行第三方验证(例如 Zod)? → 先禁用 SGDS 验证,然后调用 setInvalid(bool) 并以编程方式设置 invalidFeedback

验证触发方式

SGDS 验证分为多个阶段:

  1. onChange(失去焦点后) — 用户离开字段时进行验证;如果设置了 hasFeedback,则显示反馈
  2. onSubmit — 提交前进行最终验证;如果任何字段无效,则阻止表单提交
  3. onReset — 重置表单时清除所有有效性状态和字段值

禁用的组件会完全跳过验证。

hintText 和错误消息的位置

对于大多数表单组件(<sgds-input>、<sgds-textarea>、<sgds-select>、<sgds-combo-box>、<sgds-quantity-toggle>、<sgds-file-upload>),hintText 和错误消息会共用输入容器下方的同一空间:

  • 字段无效时(且设置了 hasFeedback),错误消息会替代 hintText。
  • 错误已解决时,hintText 会重新显示。

<sgds-checkbox-group> 和 <sgds-radio-group> 的行为不同——hintText 会显示在选项上方的标签行中,并始终保持可见。错误消息则会单独显示在选项下方。

启用反馈显示

无论是否设置 hasFeedback,都会运行约束验证,但只有存在 hasFeedback 时才会显示错误消息。hasFeedback 属性接受以下值:

值行为
hasFeedback(布尔值)将原生 HTML 验证消息显示为错误文本
hasFeedback="text"与布尔值相同——仅显示文本反馈
hasFeedback="style"仅显示无效状态的边框/颜色样式,不显示文本
hasFeedback="both"同时显示无效状态样式和文本反馈

你也可以使用 invalidFeedback 覆盖显示的消息:

<sgds-input
  name="email"
  label="Email"
  type="email"
  required
  hasFeedback="both"
  invalidFeedback="Please enter a valid email address"
></sgds-input>

各组件支持的约束

组件支持的约束
<sgds-input>required、pattern、min、max、minlength、maxlength
<sgds-textarea>required、minlength、maxlength
<sgds-quantity-toggle>min、max
<sgds-datepicker>required、minDate、maxDate
<sgds-select>required
<sgds-combo-box>required
<sgds-radio-group>required
<sgds-checkbox-group>required
<sgds-checkbox>(独立使用)required
<sgds-file-upload>required(文件大小限制尚在开发中)

完整表单示例

<form id="my-form" class="d-flex-column">
  <sgds-input
    label="First Name"
    name="firstName"
    required
    hasFeedback="both"
    pattern="[A-Za-z ]+"
    invalidFeedback="Letters only"
  ></sgds-input>

  <sgds-datepicker label="Appointment Date" name="appointmentDate" required hasFeedback></sgds-datepicker>

  <sgds-radio-group label="Gender" name="gender" required hasFeedback>
    <sgds-radio value="female">Female</sgds-radio>
    <sgds-radio value="male">Male</sgds-radio>
  </sgds-radio-group>

  <sgds-checkbox-group label="Food Preference" name="food" required hasFeedback hintText="Select at least one option">
    <sgds-checkbox value="vegetarian">Vegetarian</sgds-checkbox>
    <sgds-checkbox value="halal">Halal</sgds-checkbox>
  </sgds-checkbox-group>

  <sgds-textarea label="Comments" name="comments" required minlength="3" hasFeedback></sgds-textarea>

  <sgds-button type="submit">Submit</sgds-button>
  <sgds-button type="reset" variant="ghost">Reset</sgds-button>
</form>

通过 FormData 读取表单值

在提交处理函数中使用原生 FormData API。通过组件的 selectedFiles 属性单独访问 sgds-file-upload 文件:

<script>
  const form = document.getElementById("my-form");

  form.addEventListener("submit", event => {
    event.preventDefault();
    const formData = new FormData(event.target);

    const firstName = formData.get("firstName");
    const gender = formData.get("gender");
    const comments = formData.get("comments");

    // File upload files are not in FormData automatically
    const fileUpload = document.querySelector("sgds-file-upload");
    for (let i = 0; i < fileUpload.selectedFiles.length; i++) {
      formData.append("file" + i, fileUpload.selectedFiles[i]);
    }

    // Submit formData to server
  });
</script>

自定义验证(禁用 SGDS 验证)

对于第三方验证库(例如 Zod)或完全自定义的逻辑,请先禁用 SGDS 内置验证,然后调用 setInvalid(bool),并在输入事件发生时更新 invalidFeedback。

选项 1 — 使用 noValidate 禁用单个组件的验证

目前支持 <sgds-input>、<sgds-textarea>、<sgds-combo-box>、<sgds-datepicker>、<sgds-file-upload>、<sgds-select>、<sgds-quantity-toggle>、<sgds-radio-group>、<sgds-checkbox> 和 <sgds-checkbox-group>。

<sgds-input
  noValidate
  id="keys-input"
  name="keys"
  label="Keys"
  hintText="Cannot start with special characters"
  hasFeedback="both"
></sgds-input>

<script>
  const input = document.getElementById("keys-input");

  input.addEventListener("sgds-input", e => {
    if (/^[^a-zA-Z0-9]/.test(e.target.value)) {
      e.target.setInvalid(true);
      e.target.invalidFeedback = "Keys cannot start with special characters";
    } else {
      e.target.setInvalid(false);
    }
  });
</script>
选项 2 — 使用 novalidate 在表单级别禁用验证

向 <form> 元素添加 novalidate,即可为所有子组件禁用约束验证和 SGDS 验证。然后为每个字段应用 setInvalid 逻辑。

<form id="custom-form" novalidate class="d-flex-column">
  <sgds-input id="keys-input" name="keys" label="Keys" hasFeedback="both"></sgds-input>

  <sgds-textarea id="bio-textarea" name="bio" label="Bio" hasFeedback></sgds-textarea>
</form>

<script>
  document.getElementById("keys-input").addEventListener("sgds-input", e => {
    if (/^[^a-zA-Z0-9]/.test(e.target.value)) {
      e.target.setInvalid(true);
      e.target.invalidFeedback = "Invalid key format";
    } else {
      e.target.setInvalid(false);
    }
  });

  document.getElementById("bio-textarea").addEventListener("sgds-input", e => {
    if (e.target.value.length < 10) {
      e.target.setInvalid(true);
      e.target.invalidFeedback = "Bio must be at least 10 characters";
    } else {
      e.target.setInvalid(false);
    }
  });
</script>
setInvalid(bool) 方法
参数类型说明
boolbooleantrue 会将组件标记为无效并显示 invalidFeedback;false 会清除无效状态

将 setInvalid(true) 与设置元素的 invalidFeedback 属性配合使用,以控制显示的消息。

自定义验证支持状态

组件状态
<sgds-input>✅ 已实现
<sgds-textarea>✅ 已实现
<sgds-datepicker>✅ 已实现
<sgds-checkbox> / <sgds-checkbox-group>✅ 已实现
<sgds-quantity-toggle>✅ 已实现
<sgds-radio-group>✅ 已实现
<sgds-file-upload>✅ 已实现
<sgds-select>✅ 已实现
<sgds-combo-box>✅ 已实现

面向 AI Agent

  1. 始终将 SGDS 表单组件放在 <form> 元素内,并为其设置 name 属性,使其参与表单提交和 FormData。
  2. 表单组件必须设置 hasFeedback,错误消息才会以可视方式显示——仅进行约束验证不会显示界面反馈。
  3. 如需同时显示无效状态的边框样式和错误消息文本,请使用 hasFeedback="both"。仅设置布尔属性 hasFeedback 时,只会显示消息文本。
  4. 使用 invalidFeedback 可将浏览器原生的约束验证消息替换为自定义字符串。
  5. 约束验证和阻止表单提交的行为均为内置功能——请勿额外添加提交事件监听器来复现此行为。
  6. 在提交处理程序中使用 new FormData(event.target) 读取值。上传文件时,直接从 <sgds-file-upload> 元素读取 selectedFiles。
  7. 使用自定义验证或第三方验证时,请在组件上添加 noValidate(或在表单上添加 novalidate),然后在相关事件监听器中调用 element.setInvalid(true/false) 并设置 element.invalidFeedback(输入框/文本区域使用 sgds-input,日期选择器使用 sgds-change-date,选择器/组合框/单选组/复选框组/数量切换器使用 sgds-change,文件上传使用 sgds-add-files/sgds-remove-file)。
  8. 所有表单组件(<sgds-input>、<sgds-textarea>、<sgds-datepicker>、<sgds-combo-box>、<sgds-select>、<sgds-quantity-toggle>、<sgds-radio-group>、<sgds-checkbox>、<sgds-checkbox-group> 和 <sgds-file-upload>)均通过 noValidate + setInvalid 完整支持自定义验证。
  9. 重置按钮(type="reset")会自动清除所有有效性状态和值——无需额外编写重置逻辑。
  10. 禁用的组件不参与约束验证,也不会阻止表单提交。

评论

支持 Markdown