前回の記事「SSGform + JavaScriptで確認画面付きフォームを作ってみた」では、基本的な確認画面の実装を紹介しました。 今回はその応用編として、実務で必須となる「バリデーション機能」を追加してみました。
SSGformの基本仕様については、公式サイトまたは前回の記事をご参照ください。
マークアップ作業
まずはベースとなるHTMLを作成します。今回も公式で提供されているコード例で「簡易スパム対策付きフォーム」を参考にして、フォームを作成します。
※簡易スパム対策はハニーポットフィールドと呼ばれる手法を使用します。
※reCAPTCHAはSSGForm側で設定可能です。
formタグのaction属性には、SSGformから発行された送信先URLを設定します。
<form class="form" id="contact-form" action="送信先URL" method="post">
<div class="form__screen">
<div style="display: none;"><input type="text" name="wana" /></div> <!-- name="wana"を見えない状態で設置 -->
<div class="form__group">
<label for="topic" class="form__heading">お問い合わせ項目<span class="form__heading-required">必須</span></label>
<select id="topic" name="お問い合わせ項目" required>
<option value="">選択してください</option>
<option value="項目1">項目1</option>
<option value="項目2">項目2</option>
</select>
<span class="form__error" id="error-topic"></span>
</div>
<div class="form__group">
<label for="name" class="form__heading">お名前<span class="form__heading-required">必須</span></label>
<input id="name" type="text" name="お名前" placeholder="お名前" required />
<span class="form__error" id="error-name"></span>
</div>
<div class="form__group">
<label for="email" class="form__heading">メールアドレス<span class="form__heading-required">必須</span></label>
<input id="email" type="email" name="メールアドレス" placeholder="[email protected]" required/>
<span class="form__error" id="error-email"></span>
</div>
<div class="form__group">
<label for="message" class="form__heading">お問い合わせ内容<span class="form__heading-required">必須</span></label>
<textarea id="message" name="お問い合わせ内容" placeholder="お問い合わせ内容" required></textarea>
<span class="form__error" id="error-message"></span>
</div>
<button class="form__btn" id="form-confirm" type="button">確認画面</button>
</div>
</form>確認画面を挟んで送信を行うため、formタグ内に確認画面部分のコードを追加します。
<form class="form" id="contact-form" action="送信先URL" method="post">
<!-- 入力画面の要素 -->
(省略)
<!-- 確認画面の要素 -->
<div id="confirmation-screen" class="confirmation" style="display: none;">
<p>以下の内容で送信します。よろしいですか?</p>
<div class="confirmation__group">
<h3>お問い合わせ項目:</h3>
<p id="confirm-topic"></p>
</div>
<div class="confirmation__group">
<h3>お名前:</h3>
<p id="confirm-name"></p>
</div>
<div class="confirmation__group">
<h3>メールアドレス:</h3>
<p id="confirm-email"></p>
</div>
<div class="confirmation__group">
<h3>お問い合わせ内容:</h3>
<p id="confirm-message"></p>
</div>
<div class="confirmation__btn-wrapper">
<button class="confirmation__btn" id="confirm-back">戻る</button>
<button class="confirmation__btn" id="confirm-submit" type="submit">送信する</button>
</div>
</div>
</form>これでフォームの作成は完了です。
※画像では見やすくするため、スタイル調整を行っています。

JavaScriptによるバリデーションと確認画面の実装
今回、サニタイズ(無害化)のために「DOMPurify」を導入しています。
これは、悪意のあるユーザーが入力欄にスクリプトを混入させる「XSS(クロスサイトスクリプティング)攻撃」を防ぐためです。
コード内では textContent を使用しているため、基本的にはスクリプト注入のリスクは低いですが、単一の対策に頼るのではなく、多層防御の一環として「保険」のために「DOMPurify」を併用し、セキュリティを強化しました。
また「DOMPurify」の詳しい内容については、こちらの記事をご参照ください。
ライブラリのインストールします(npm経由)
npm install dompurifyインストールした「DOMPurify」を使用して実装していきます。
import DOMPurify from 'dompurify';
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('contact-form'); // フォーム要素の参照
const formWrap = document.querySelector('.form__screen'); // 入力画面の要素の参照
const confirmationScreen = document.getElementById('confirmation-screen'); // 確認画面要素の参照
const confirmTopic = document.getElementById('confirm-topic'); // 確認画面の各フィールドの参照(topic)
const confirmName = document.getElementById('confirm-name'); // 確認画面の各フィールドの参照(name)
const confirmEmail = document.getElementById('confirm-email'); // 確認画面の各フィールドの参照(email)
const confirmMessage = document.getElementById('confirm-message'); // 確認画面の各フィールドの参照(message)
const formConfirmButton = document.getElementById('form-confirm'); // フォームから確認画面に進むボタンの参照
const confirmBack = document.getElementById('confirm-back'); // 確認画面からフォームへ戻るボタンの参照
// エラーメッセージ要素を取得
const errorTopic = document.getElementById('error-topic');
const errorName = document.getElementById('error-name');
const errorEmail = document.getElementById('error-email');
const errorMessage = document.getElementById('error-message');
// エラーメッセージの表示・非表示を切り替える関数
const displayError = (errorElement, message) => {
if (message) {
errorElement.textContent = message;
errorElement.style.display = 'block';
} else {
errorElement.textContent = '';
errorElement.style.display = 'none';
}
};
// フォームのバリデーション関数
const validateForm = () => {
let isValid = true; // バリデーション結果を保持するフラグ
// フォームの入力値を取得 (trim() = 先頭と末尾にある空白文字を削除)
const formData = {
topic: form.elements['お問い合わせ項目'].value.trim(),
name: form.elements['お名前'].value.trim(),
email: form.elements['メールアドレス'].value.trim(),
message: form.elements['お問い合わせ内容'].value.trim()
};
// 1. お問い合わせ項目のチェック
if (formData.topic === '') {
displayError(errorTopic, 'お問い合わせ項目を選択してください。');
isValid = false;
} else {
displayError(errorTopic, '');
}
// 2. お名前のチェック
if (formData.name === '') {
displayError(errorName, 'お名前を入力してください。');
isValid = false;
} else {
// 例: 20文字制限
if (formData.name.length > 20) {
displayError(errorName, 'お名前は20文字以内で入力してください。');
isValid = false;
} else { // 文字数制限クリア
displayError(errorName, '');
}
}
// 3. メールアドレスのチェック
const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
if (formData.email === '') {
displayError(errorEmail, 'メールアドレスを入力してください。');
isValid = false;
} else if (!emailRegex.test(formData.email)) { // フォーマットチェック
displayError(errorEmail, '有効なメールアドレス形式で入力してください。');
isValid = false;
} else {
displayError(errorEmail, '');
}
// 4. お問い合わせ内容のチェック
if (formData.message === '') {
displayError(errorMessage, 'お問い合わせ内容を入力してください。');
isValid = false;
} else {
displayError(errorMessage, '');
}
return { isValid, formData }; // バリデーション結果とフォームデータを返す
};
// 「確認画面」のボタンをクリックしたときの処理
formConfirmButton.addEventListener('click', () => {
const { isValid, formData } = validateForm();
// もしバリデーションに失敗したら、確認画面に進まない
if (!isValid) {
return;
}
// 「DOMPurify」ライブラリでサニタイズする
const sanitizedTopic = DOMPurify.sanitize(formData.topic);
const sanitizedName = DOMPurify.sanitize(formData.name);
const sanitizedEmail = DOMPurify.sanitize(formData.email);
const sanitizedMessage = DOMPurify.sanitize(formData.message);
// サニタイズした値を確認画面に表示
confirmTopic.textContent = sanitizedTopic;
confirmName.textContent = sanitizedName;
confirmEmail.textContent = sanitizedEmail;
confirmMessage.textContent = sanitizedMessage;
// 入力フォームを非表示にして確認画面を表示
formWrap.style.display = 'none'; // 入力フォームを非表示
confirmationScreen.style.display = 'block'; // 確認画面を表示
window.scrollTo({ top: 0, behavior: 'smooth' });
});
// 「戻る」ボタンをクリックしたとき
confirmBack.addEventListener('click', (event) => {
event.preventDefault(); // フォーム送信をキャンセル
confirmationScreen.style.display = 'none'; // 確認画面を非表示
formWrap.style.display = 'block'; // 入力フォームを表示
});
};未入力時のバリデーションとして空欄のまま「確認画面」をクリックすると、エラーメッセージが表示されます。

またメールアドレスの形式チェックとして不正な形式のメールアドレスを入力した場合も、エラーメッセージが出るようになりました。

エラーがなければ確認画面へ遷移し、内容に問題がなければ送信が実行されます。
送信完了画面への遷移は前回の記事をご参照ください。

まとめ
今回はSSGformを使ってバリデーション + 確認画面付きのお問い合わせフォームを作成してみました。
バリデーションを加えることで、ユーザーの入力ミスを減らし、より実用的なお問い合わせフォームになります。

