12k
All articles

htmxを使ったシンプルなフォームバリデーション

HTML5バリデーション属性とサーバーサイドのインラインフィードバックを組み合わせ、大量のJavaScriptを書かずにhtmxでクリーンなフォームを構築する方法を解説。

OpenReplay Team
OpenReplay Team
htmxを使ったシンプルなフォームバリデーション

フォームバリデーションは、大量のJavaScriptを書く必要はありません。バリデーション状態、エラーメッセージ、DOM更新を手動で管理することに疲れているなら、htmxは驚くほどシンプルな代替手段を提供します。最小限のコードで最大限のユーザーエクスペリエンスを実現する、クライアントサイドとサーバーサイドの両方のバリデーション実装方法を探ってみましょう。

重要なポイント

  • htmxはhx-validate="true"を使用してHTML5バリデーションで最小限のJavaScriptでフォームバリデーションを可能にします
  • サーバーサイドインラインバリデーションは、複雑なクライアントサイド状態管理なしでリアルタイムフィードバックを提供します
  • バリデーションが正しく動作するには、適切なhtmx属性の配置とイベントハンドリングが重要です
  • クライアントとサーバーのバリデーションを組み合わせることで、より少ないコードでアクセシブルでユーザーフレンドリーなフォームを作成できます

htmxを使用したクライアントサイドバリデーション

即座のフィードバックのためのhx-validate

クライアントサイドバリデーションを追加する最もシンプルな方法は、フォームにhx-validate="true"を設定することです。これにより、htmxはリクエストを送信する前にHTML5バリデーション属性をチェックします:

<form hx-post="/submit" hx-validate="true">
  <input type="email" name="email" required>
  <input type="text" name="username" 
         pattern="[a-zA-Z0-9]{3,20}" 
         title="3-20 alphanumeric characters">
  <button type="submit">Submit</button>
</form>

このアプローチは、ブラウザの組み込みバリデーションを活用し、JavaScriptを書くことなく即座のフィードバックを提供します。

htmx-validation拡張機能による高度なルール

より複雑なバリデーションシナリオには、htmx-validation拡張機能がカスタムルールを提供します:

<script src="https://unpkg.com/htmx.org/dist/ext/validate.js"></script>

<form hx-post="/submit" hx-ext="validate">
  <input name="password" type="password" 
         data-validate='{"required": true, "minLength": 8}'>
  <input name="confirm" type="password" 
         data-validate='{"equalTo": "password"}'>
  <button type="submit">Submit</button>
</form>

この拡張機能はカスタムバリデーション関数をサポートしており、HTML5属性では処理できないビジネスロジックに最適です。

サーバーサイドインラインバリデーション

リアルタイムフィールドバリデーション

最も強力なhtmxフォームバリデーションパターンは、サーバーサイドロジックとインライン更新を組み合わせたものです。ユーザーが入力している間に個別のフィールドをバリデーションする方法を以下に示します:

<form hx-post="/register">
  <div>
    <label for="email">Email</label>
    <input name="email" id="email" 
           hx-post="/validate/email" 
           hx-trigger="blur, keyup delay:500ms"
           hx-target="next .error"
           hx-swap="innerHTML">
    <span class="error"></span>
  </div>
  <button type="submit">Register</button>
</form>

サーバーエンドポイントはバリデーションフィードバックを返します:

# Python/Flask例
@app.route('/validate/email', methods=['POST'])
def validate_email():
    email = request.form.get('email')
    if not email or '@' not in email:
        return '<span class="text-red">Invalid email format</span>'
    if email_exists_in_db(email):
        return '<span class="text-red">Email already taken</span>'
    return '<span class="text-green">✓ Available</span>'

部分レスポンスによる完全なフォームバリデーション

完全なフォームバリデーションには、エラー状態を含む全体のフォームを返します:

<form id="contact-form" 
      hx-post="/contact" 
      hx-target="this" 
      hx-swap="outerHTML">
  <input name="email" type="email" required>
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>

サーバーは、バリデーションが失敗した場合はエラークラスとメッセージを含むフォームを、成功した場合は成功メッセージを返します。

よくある落とし穴と解決策

ボタン vs フォーム属性

よくある間違いは、フォームではなく送信ボタンにhx-postを配置することです:

<!-- 間違い:バリデーションがトリガーされません -->
<form hx-validate="true">
  <button hx-post="/submit">Submit</button>
</form>

<!-- 正しい:バリデーションが動作します -->
<form hx-post="/submit" hx-validate="true">
  <button type="submit">Submit</button>
</form>

バリデーションイベントの処理

htmxは、バリデーションフローをきめ細かく制御するためのイベントを提供します:

// バリデーション前にインターセプト
document.body.addEventListener('htmx:configRequest', function(evt) {
  if (evt.target.matches('[data-confirm]')) {
    evt.preventDefault()
    if (confirm(evt.target.dataset.confirm)) {
      evt.detail.issueRequest()
    }
  }
})

// サーバーバリデーションエラーの処理
document.body.addEventListener('htmx:responseError', function(evt) {
  if (evt.detail.xhr.status === 422) {
    // サーバーからのバリデーションエラーを表示
    const errors = JSON.parse(evt.detail.xhr.response)
    showValidationErrors(errors)
  }
})

アクセシブルなバリデーションのベストプラクティス

スクリーンリーダー用に適切なARIA属性を常に含めてください:

<input name="email" 
       aria-invalid="true" 
       aria-describedby="email-error">
<span id="email-error" role="alert">
  Please enter a valid email
</span>

パスワードなど、常時バリデーションが煩わしい可能性があるフィールドには、keyupではなくhx-trigger="blur"を使用してください。検索やユーザー名の可用性チェックには、keyup delay:500msが良いバランスを提供します。

まとめ

htmxフォームバリデーションは、バリデーションロジックをあるべき場所(サーバー)に保ちながら、ユーザーが期待するスムーズで応答性の高いエクスペリエンスを提供することで優れています。即座のフィードバックのためのクライアントサイドバリデーションを選択するか、複雑なルールのためのサーバーサイドバリデーションを選択するかに関わらず、htmxはユーザーエクスペリエンスを向上させながら書くJavaScriptを削減します。基本的なニーズにはhx-validate="true"から始めて、洗練された本番対応フォームのためにインラインバリデーションを段階的に追加してください。

よくある質問

htmxバリデーションは、シンプルなフォームでサーバーなしで動作しますか?

はい、htmxは基本的なクライアントサイドバリデーションのために、hx-validate=trueでHTML5バリデーション属性を使用できます。ただし、htmxの真の強みは、複雑なビジネスルールやデータベースチェックを実装しながらスムーズなユーザーエクスペリエンスを維持できるサーバーサイドバリデーションにあります。

htmxでバリデーションが失敗した場合にフォーム送信を防ぐにはどうすればよいですか?

hx-validate=trueを使用する場合、HTML5バリデーションが失敗するとhtmxは自動的に送信を防ぎます。サーバーサイドバリデーションの場合は、200以外のステータスコードを返すか、htmx:validation:failedなどのhtmxイベントを使用して送信を停止し、エラーメッセージを表示します。

バリデーションにおけるhx-trigger blurとkeyupの違いは何ですか?

blurトリガーは、ユーザーがフィールドを離れるときにバリデーションを行い、入力中の邪魔を減らします。keyupトリガーは、ユーザーが入力している間にバリデーションを行い、即座のフィードバックを提供します。パスワードフィールドにはblurを、ユーザー名の可用性チェックにはdelayを伴うkeyupを使用してください。

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.