バリデーター

フォームに入力された内容を、ブラウザ上で入力チェックするための JavaScript によるバリデータです。

a-blog cms では標準機能でサーバーサイドのバリデーター機能が搭載されています。こちらはフォームに入力された内容を、サーバーに送信するとサーバーからのレスポンスとしてエラー結果が返ってくるものでしたが、JavaScript で入力チェックすることで、ブラウザ側でエラーを判定されるため、エラーがあったときのレスポンスが高速になる他、サーバーに余分な負荷をかけずに済むというメリットがあります。

使い方

JavaScript によるバリデーターの使い方を説明します。

クラスの付与

フォームでJavaScript によるバリデーターを使用できるようにするために、 js-validator クラスをフォーム要素に適用します。

<form action="" method="post" class="js-validator" enctype="multipart/form-data">
...
</form>

バリデーターオプションを指定する

どのような条件で入力チェックをするかということを指定します。例えば、必須入力やメールアドレスの形式チェックなどです。

バリデーターオプションは、サーバーサイドのバリデーターと同様の形式で指定可能です。

<input type="hidden" name="[対象の項目名]:validator#[オプション名]"  />

チェック対象のフォーム項目のname属性を指定し、最後にオプション名を指定します。

バリデーターオプションは一部を除いてサーバーサイドのバリデーターと同じオプションが利用可能です。詳しくは以下のドキュメントを参照してください。


バリデーションエラー時に表示する要素を紐付ける

バリデーターオプションとバリデーションに失敗したときに表示する要素と紐づけます。

まず、バリデーターオプションを指定している要素に任意の id 属性を指定します。

<!-- バリデーターオプションを指定している要素のid属性にname-v-requiredを指定 -->
<input type="hidden" name="name:validator#required" id="name-v-required">

バリデーションに失敗したときに表示させたい要素 のdata-validator-label 属性もしくは、label 要素の for 属性に、先程指定した id 属性の値を設定します。

<th>ハンドルネーム (必須)</th>
<td>
  <input type="text" name="name" value="{name}">
  <input type="hidden" name="field[]" value="name">
  <input type="hidden" name="name:validator#required" id="name-v-required">
  <div role="alert" aria-live="assertive">
    <div data-validator-label="name-v-required" class="validator-result-{name:v#required}">
      <p class="error-text">
        <span class="acms-icon acms-icon-attention" aria-hidden="true"></span>
        ハンドルネームを入力してください。
      </p>
    </div>
  </div>
</td>

上記の実装を行うことで、バリデーション時に指定した要素の class 属性が書き換えられます。それにより、表示/非表示のCSSが操作されることでエラーメッセージとして動作します。

動作確認

これで、JavaScript によるバリデーターを動作させるための最低限の実装は完了です。実際にブラウザ上で動作確認をしてみてください。

以下は、JavaScript によるバリデーターを実装したフォームのサンプルコードになります。

<h3 class="contact-form-heading">お問い合わせ情報</h3>
<ul class="contact-form">
	<li class="contact-form-group">
		<div class="contact-form-label">
			<label for="description">ご用件</label><span class="label-required">必須</span>
			<div class="valid-mark" data-validator="description">
				<span class="acms-icon acms-icon-checklist"></span>
			</div>
		</div>
		<div class="contact-form-control">
			<select id="description" class="form-select" name="description" data-validator="description">
				<option value=""<!-- BEGIN_IF [{description}/em] --> selected="selected"<!-- END_IF -->>選択してください</option>
				<option value="ご質問"{description:selected#ご質問}>ご質問</option>
				<option value="ご要望"{description:selected#ご要望}>ご要望</option>
				<option value="資料請求"{description:selected#資料請求}>資料請求</option>
				<option value="その他"{description:selected#その他}>その他</option>
			</select>
			<input type="hidden" name="field[]" value="description">
			<input type="hidden" name="description:v#required" id="description-v-required">

			<div role="alert" aria-live="assertive">
				<div data-validator-label="description-v-required" class="validator-result-{description:v#required}">
					<p class="error-text"><span class="acms-icon acms-icon-attention" aria-hidden="true"></span>お問い合わせ種類を選択してください。</p>
				</div>
			</div>
		</div>
	</li>
	<li class="contact-form-group">
		<div class="contact-form-label">
			<label for="inquiry">お問い合わせ内容</label><span class="label-required">必須</span>
			<div class="valid-mark" data-validator="inquiry">
				<span class="acms-icon acms-icon-checklist"></span>
			</div>
		</div>
		<div class="contact-form-control">
			<textarea id="inquiry" name="inquiry" rows="5" class="acms-form-width-full" placeholder="お問い合わせ内容を入力してください。" data-validator="inquiry">{inquiry}</textarea>
			<input type="hidden" name="field[]" value="inquiry">
			<input type="hidden" name="inquiry:v#required" id="inquiry-v-required">
			<input type="hidden" name="inquiry:c" value="KV">

			<div role="alert" aria-live="assertive">
				<div data-validator-label="inquiry-v-required" class="validator-result-{inquiry:v#required}">
					<p class="error-text"><span class="acms-icon acms-icon-attention" aria-hidden="true"></span>お問い合わせ内容を入力してください。</p>
				</div>
			</div>
		</div>
	</li>
</ul>


<h3 class="contact-form-heading">お客様情報</h3>
<ul class="contact-form">
	<li class="contact-form-group">
		<p class="contact-form-label"><label for="organization">会社名</label></p>
		<div class="contact-form-control">
			<input id="organization" type="text" name="organization" autocomplete="organization" value="{organization}" class="acms-form-width-full" placeholder="例)株式会社サンプルサイト">
			<input type="hidden" name="field[]" value="organization">
			<input type="hidden" name="organization:c" value="KV">
		</div>
	</li>
	<li class="contact-form-group">
		<div class="contact-form-label">
			お名前<span class="label-required">必須</span>
			<div class="valid-mark" data-validator="name">
				<span class="acms-icon acms-icon-checklist"></span>
			</div>
		</div>
		<div class="contact-form-control">
			<label for="name" class="acms-hide-visually">名前</label>
			<input id="name" type="text" name="name" autocomplete="name" class="acms-form-width-full" value="{name}" placeholder="例)山田 太郎" data-validator="name">
			<input type="hidden" name="field[]" value="name">
			<input type="hidden" name="name:v#required" id="name-v-required">
			<input type="hidden" name="name:c" value="KV">

			<div role="alert" aria-live="assertive">
				<div data-validator-label="name-v-required" class="validator-result-{name:v#required}">
					<p class="error-text"><span class="acms-icon acms-icon-attention" aria-hidden="true"></span>名前を入力してください。</p>
				</div>
			</div>
		</div>
	</li>
	<li class="contact-form-group">
		<div class="contact-form-label">
			<label for="email">メールアドレス</label><span class="label-required">必須</span>
			<div class="valid-mark" data-validator="email">
				<span class="acms-icon acms-icon-checklist"></span>
			</div>
		</div>
		<div class="contact-form-control">
			<input id="email" type="email" name="email" autocomplete="email" value="{email}" class="acms-form-width-full" placeholder="例)info@example.com" data-validator="email">
			<input type="hidden" name="field[]" value="email">
			<input type="hidden" name="email:v#required" id="email-v-required">
			<input type="hidden" name="email:v#email" id="email-v-email">
			<input type="hidden" name="email:c" value="a">

			<div data-validator-label="email-v-required" class="validator-result-{email:v#required}">
				<p class="error-text"><span class="acms-icon acms-icon-attention" aria-hidden="true"></span>メールアドレスを入力してください。</p>
			</div>
			<div role="alert" aria-live="assertive">
				<div data-validator-label="email-v-email" class="validator-result-{email:v#email}">
					<p class="error-text"><span class="acms-icon acms-icon-attention" aria-hidden="true"></span>正しいメールアドレスを入力してください。</p>
				</div>
			</div>
		</div>
	</li>
	<li class="contact-form-group">
		<p class="contact-form-label"><label for="tel">お電話番号</label></p>
		<div class="contact-form-control">
			<input id="tel" type="tel" name="tel" autocomplete="tel" value="{tel}" size="12" class="acms-form-width-medium" placeholder="例)000-000-0000">
			<input type="hidden" name="field[]" value="tel">
			<input type="hidden" name="tel:c" value="n">
		</div>
	</li>
	<li class="contact-form-group">
		<p class="contact-form-label">ご住所<span class="label-required">必須</span></p>
		<div class="contact-form-control">
			<script src="https://yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
			<input type="hidden" class="p-country-name" value="Japan">
			<div class="acms-form-group">
				<span class="acms-margin-right-mini">
					<label for="postal-code" class="acms-hide-visually">郵便番号</label>
					<input type="text" name="postal-code" autocomplete="postal-code" value="{postal-code}" id="postal-code" class="js-insert-hyphen p-postal-code acms-form-width-mini" size="9" maxlength="8" placeholder="例)000-0000" data-validator="postal-code">
					<input type="hidden" name="field[]" value="postal-code">
					<input type="hidden" name="postal-code:c" value="a">
				</span>

				<label for="address-level1" class="acms-hide-visually">都道府県</label>
				<select class="p-region form-select" name="address-level1" autocomplete="address-level1" id="address-level1" data-validator="address-level1">
					<option value=""<!-- BEGIN_IF [{address-level1}/em] --> selected="selected"<!-- END_IF -->>都道府県</option>
					<option value="北海道"{address-level1:selected#北海道}>北海道</option>

					<option value="青森県"{address-level1:selected#青森県}>青森県</option>
					<option value="岩手県"{address-level1:selected#岩手県}>岩手県</option>
					<option value="宮城県"{address-level1:selected#宮城県}>宮城県</option>
					<option value="秋田県"{address-level1:selected#秋田県}>秋田県</option>
					<option value="山形県"{address-level1:selected#山形県}>山形県</option>
					<option value="福島県"{address-level1:selected#福島県}>福島県</option>
					<option value="茨城県"{address-level1:selected#茨城県}>茨城県</option>
					<option value="栃木県"{address-level1:selected#栃木県}>栃木県</option>
					<option value="群馬県"{address-level1:selected#群馬県}>群馬県</option>

					<option value="埼玉県"{address-level1:selected#埼玉県}>埼玉県</option>
					<option value="千葉県"{address-level1:selected#千葉県}>千葉県</option>
					<option value="東京都"{address-level1:selected#東京都}>東京都</option>
					<option value="神奈川県"{address-level1:selected#神奈川県}>神奈川県</option>
					<option value="新潟県"{address-level1:selected#新潟県}>新潟県</option>
					<option value="富山県"{address-level1:selected#富山県}>富山県</option>
					<option value="石川県"{address-level1:selected#石川県}>石川県</option>
					<option value="福井県"{address-level1:selected#福井県}>福井県</option>
					<option value="山梨県"{address-level1:selected#山梨県}>山梨県</option>

					<option value="長野県"{address-level1:selected#長野県}>長野県</option>
					<option value="岐阜県"{address-level1:selected#岐阜県}>岐阜県</option>
					<option value="静岡県"{address-level1:selected#静岡県}>静岡県</option>
					<option value="愛知県"{address-level1:selected#愛知県}>愛知県</option>
					<option value="三重県"{address-level1:selected#三重県}>三重県</option>
					<option value="滋賀県"{address-level1:selected#滋賀県}>滋賀県</option>
					<option value="京都府"{address-level1:selected#京都府}>京都府</option>
					<option value="大阪府"{address-level1:selected#大阪府}>大阪府</option>
					<option value="兵庫県"{address-level1:selected#兵庫県}>兵庫県</option>

					<option value="奈良県"{address-level1:selected#奈良県}>奈良県</option>
					<option value="和歌山県"{address-level1:selected#和歌山県}>和歌山県</option>
					<option value="鳥取県"{address-level1:selected#鳥取県}>鳥取県</option>
					<option value="島根県"{address-level1:selected#島根県}>島根県</option>
					<option value="岡山県"{address-level1:selected#岡山県}>岡山県</option>
					<option value="広島県"{address-level1:selected#広島県}>広島県</option>
					<option value="山口県"{address-level1:selected#山口県}>山口県</option>
					<option value="徳島県"{address-level1:selected#徳島県}>徳島県</option>
					<option value="香川県"{address-level1:selected#香川県}>香川県</option>

					<option value="愛媛県"{address-level1:selected#愛媛県}>愛媛県</option>
					<option value="高知県"{address-level1:selected#高知県}>高知県</option>
					<option value="福岡県"{address-level1:selected#福岡県}>福岡県</option>
					<option value="佐賀県"{address-level1:selected#佐賀県}>佐賀県</option>
					<option value="長崎県"{address-level1:selected#長崎県}>長崎県</option>
					<option value="熊本県"{address-level1:selected#熊本県}>熊本県</option>
					<option value="大分県"{address-level1:selected#大分県}>大分県</option>
					<option value="宮崎県"{address-level1:selected#宮崎県}>宮崎県</option>
					<option value="鹿児島県"{address-level1:selected#鹿児島県}>鹿児島県</option>

					<option value="沖縄県"{address-level1:selected#沖縄県}>沖縄県</option>
				</select>
				<input type="hidden" name="field[]" value="address-level1">
			</div>
			<div class="acms-grid">
				<div class="acms-col-12">
					<label for="address1" class="acms-hide-visually">市区町村、番地</label>
					<input id="address1" type="text" name="address1" autocomplete="address-level2 address-line1" value="{address1}" size="12" class="p-locality p-street-address p-extended-address acms-form-width-full acms-margin-bottom-small" placeholder="例)〇〇市〇〇区〇〇町123" data-validator="address1">
					<input type="hidden" name="field[]" value="address1">
				</div>
				<div class="acms-col-12">
					<label for="address2" class="acms-hide-visually">建物名</label>
					<input id="address2" type="text" name="address2" autocomplete="address-line2" value="{address2}" size="12" class="acms-form-width-full" placeholder="例)〇〇〇ビル〇F">
					<input type="hidden" name="field[]" value="address2">
				</div>
			</div>
			<input type="hidden" name="postal-code:v#required" id="postal-code-v-required">
			<input type="hidden" name="address-level1:v#required" id="address-level1-v-required">
			<input type="hidden" name="address1:v#required" id="address1-v-required">
			<input type="hidden" name="address1:c" value="KV">
			<input type="hidden" name="address2:c" value="KV">

			<div role="alert" aria-live="assertive">
				<div data-validator-label="postal-code-v-required" class="validator-result-{postal-code:v#required}">
					<p class="error-text"><span class="acms-icon acms-icon-attention" aria-hidden="true"></span>郵便番号が入力されていません。</p>
				</div>
				<div data-validator-label="address-level1-v-required" class="validator-result-{address-level1:v#required}">
					<p class="error-text"><span class="acms-icon acms-icon-attention" aria-hidden="true"></span>都道府県が選択されていません。</p>
				</div>
				<div data-validator-label="address1-v-required" class="validator-result-{address1:v#required}">
					<p class="error-text"><span class="acms-icon acms-icon-attention" aria-hidden="true"></span>市区町村、番地が入力されていません。</p>
				</div>
			</div>
		</div>
	</li>
</ul>

JavaScript によるバリデーターを利用すると画面遷移なしで即座にエラーを表示できるため、エンドユーザーに対するレスポンス向上につながります。記述は若干多くなりますが、積極的に利用してみてください。

設定

以下の設定が /js/config.js で設定できます。



設定項目 説明 デフォルト値
validatorFormMark バリデーターを使うform要素のセレクター 'form.js-validator'
validatorResultClass バリデーション実行後に要素につけるクラス属性(エラーメッセージの表示切り替えに利用できます。) 'validator-result-'
validatorOkClass バリデートにパスした時につけるクラス 'valid'
validatorNgClass バリデートに引っかかった場合につけるクラス 'invalid'

バリデーション実行結果によってスタイルを切り替える

validatorOkClass と validatorNgClass の設定は data-validator 属性に入力チェック対象の input 要素、 select 要素、 textarea 要素 に指定されている name 属性の値を指定することで、バリデーションの実行結果によって任意の class 属性を付与します。

これにより、バリデーション実行結果によってスタイルを切り替えることが可能です。

例えば、以下のように入力チェックをする input 要素に対して、data-validator 属性を設定することで、バリデーションに失敗した場合、ボーダーカラーを切り替えることが可能です。

<input type="text" name="name" value="{name}" data-validator="name">
input[type="text"].invalid {
  border-color: #ea868f;
}