コンテンツにスキップ

097. Client-side Validation(ブラウザでの検証:送信前に「超速」でミスを指摘する)

原理:サーバーに聞く前の「最後のアドバイス」

一秒でも早く間違いを教えたい

ユーザーがフォームに文字を打っているとき、手を止めて「送信」ボタンを押すまで間違いに気づかないのは、少し不親切です。 「このユーザー名は既に使われています」 「パスワードが短すぎます」 こうしたアドバイスを、サーバーにリクエストを送る直前、あるいは入力している最中にブラウザ側でパッと出すのが「クライアントサイド(ブラウザ側)バリデーション」の役割です。

HTMXを使えば、複雑なJavaScriptのライブラリに頼らなくても、ブラウザが持つ「検証エンジン」と対話して、高度なチェックを実現できます。


実践:リアルタイムな「ダメ出し」と「励まし」

1. 「htmx:validation:validate」イベントの活用

HTMXは送信の直前に、自分自身で検証を行うチャンスを私たちにくれます。

<form hx-post="/api/signup">
    <input id="age" type="number" name="age" 
           hx-on:htmx:validation:validate="
               if(this.value < 18) {
                   this.setCustomValidity('18歳以上である必要があります');
                   htmx.config.refreshOnHistoryMiss = true; // (※イメージです)
               } else {
                   this.setCustomValidity('');
               }
           ">
    <button type="submit">登録</button>
</form>
setCustomValidity は、ブラウザ標準の「エラーメッセージ表示機能」を呼び出すJavaScriptの命令です。HTMXはこれと完璧に連携します。

2. インプットごとのリアルタイムチェック

「入力が終わった(フォーカスが外れた)」瞬間に、サーバーに聞かずにブラウザのルールだけで判定を下すようなUIに最適です。

3. ステップ・バイ・ステップ解説

  1. ルールの定義: HTMLの標準属性(requiredなど)だけでは足りない「独自のルール」を決めます(例:2つのパスワード欄が一致しているか)。
  2. イベントの購読: hx-on:htmx:validation:validate(または htmx:confirm)を使って、送信前に割り込みます。
  3. メッセージの表示: エラーがあれば setCustomValidity でメッセージをセットします。これで、HTMXは送信を中止し、ブラウザがエラーを出してくれます。

比較:標準属性 vs 高度なクライアント検証

標準属性 (required, type="email"など)

  • 手軽さ: 最高(属性を書くだけ)。
  • 限界: 複雑なビジネスルール(「月曜日はこの値はダメ」など)は書けない。

高度なクライアント検証 (hx-onなど)

  • 手軽さ: 少しコードが必要。
  • 自由度: 高い。JavaScriptを使って自由なルールを書ける。

まとめ:初心者のための「即時フィードバック」

クライアントサイドでの検証を磨き上げることは、ユーザーとの「対話のテンポ」を速めることに他なりません。

  • ブラウザを信じる: 自分でエラー用の div を作って出し入れするよりも、ブラウザ標準の「吹き出し」を使ったほうが、色々な端末や環境で正しく動きます。
  • 「changed」との組み合わせ: リアルタイム検証をやりすぎて、一文字打つたびに怒られるのはストレスです。hx-trigger="change" などを使って、一区切りついた時にチェックするのがコツです。
  • 最終防衛線ではない: 何度も繰り返しますが、これは「親切心」のための機能です。悪意のあるユーザーはこれを簡単に突破できるため、次の記事で学ぶ「サーバー側での検証」が必ずセットで必要になります。

打ち終わった瞬間の、安心感を。クライアントサイド・バリデーションを使いこなして、ユーザーを迷わせない、迷ってもすぐ直せる、軽快なフォーム体験を提供してください。次の記事では、本当の正解を知る「サーバーサイドでの厳格検証(098. Server-side Validation)」をご紹介します。