sgds-forms について
sgds-formsは、ブラウザー標準のフォーム動作に対応するSGDSフォームコンポーネントの検証パターンを説明します。組み込み制約、フィードバック、送信データ、カスタム検証の扱いを開発者向けに案内します。
主な機能
- 01標準フォーム送信とFormData
- 02組み込みの制約検証
- 03設定可能な検証フィードバック
- 04コンポーネント単位またはフォーム全体の制御
- 05setInvalidによるカスタム検証
活用シーン
- 01入力が無効な場合の送信阻止
- 02ブラウザーまたは独自の検証メッセージ表示
- 03SGDSフィールドと外部検証の連携
インストール
コマンドをコピーしてターミナルで実行します。
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 を追加します
フィールドが無効な場合に送信を防ぎますか? → 組み込み機能です。追加のコードは不要です
送信されたフィールドの値を読み取りますか? → submit ハンドラーで 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 のバリデーションは、次のように段階的に実行されます。
- onChange(フォーカスを外した後) — ユーザーがフィールドから離れたときに検証します。
hasFeedbackが設定されている場合は、フィードバックを表示します - onSubmit — 送信前に最終検証を実行し、無効なフィールドがある場合はフォームの送信を阻止します
- 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 (boolean) | ネイティブの HTML バリデーションメッセージをエラーテキストとして表示します |
hasFeedback="text" | boolean と同じです。テキストのフィードバックのみを表示します |
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 を使用します。sgds-file-upload のファイルには、コンポーネントの selectedFiles プロパティから別途アクセスします。
<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) メソッド
| パラメーター | 型 | 説明 |
|---|---|---|
bool | boolean | true はコンポーネントを無効としてマークし、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 エージェント向け
- SGDS のフォームコンポーネントは、フォーム送信および
FormDataに含めるため、必ずname属性を指定した<form>要素内に配置してください。 - エラーメッセージを視覚的に表示するには、フォームコンポーネントに
hasFeedbackを指定する必要があります。制約検証だけでは UI にフィードバックは表示されません。 - 無効な状態を示す枠線とエラーメッセージの両方を表示するには、
hasFeedback="both"を使用してください。単純なブール値のhasFeedbackでは、メッセージのテキストのみが表示されます。 - ブラウザー標準の制約検証メッセージをカスタム文字列で置き換えるには、
invalidFeedbackを使用してください。 - 制約検証とフォーム送信のブロックは組み込みで提供されています。この動作を再現するための送信イベントリスナーを追加しないでください。
- 送信ハンドラーでは
new FormData(event.target)を使用して値を読み取ってください。ファイルのアップロードでは、<sgds-file-upload>要素のselectedFilesを直接読み取ってください。 - カスタム検証またはサードパーティー製の検証を使用する場合は、コンポーネントに
noValidate(またはフォームにnovalidate)を指定し、該当するイベントリスナー内でelement.setInvalid(true/false)を呼び出し、element.invalidFeedbackを設定してください(入力/テキストエリアではsgds-input、日付選択ではsgds-change-date、セレクト/コンボボックス/ラジオグループ/チェックボックスグループ/数量切り替えではsgds-change、ファイルアップロードではsgds-add-files/sgds-remove-file)。 - すべてのフォームコンポーネント(
<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によるカスタム検証を完全にサポートしています。 - リセットボタン(
type="reset")を使うと、すべての有効性状態と値が自動的にクリアされるため、追加のリセット処理は不要です。 - 無効化されたコンポーネントは制約検証の対象外となり、フォーム送信をブロックすることはありません。