Bootstrap 4 のバリデーション用クラスの使い方

Bootstrap 3 では、バリデーションの結果に .has-warning.has-error などのクラスを追加することで、フォーム部品の色を変えたりできますが、Bootstrap 4 は少し事情が違ったのでまとめておきます。

ブラウザ側の機能を使ってバリデーションする場合

最近のブラウザだと、<input type="email">required 属性を設定することで、ブラウザ側で入力をチェックしてくれますが、Bootstrap 4 はこのチェック結果を利用してフォーム部品の色などを変えることができます。

<form class="was-validated" novalidate>
  <div class="form-group">
    <label for="name">お名前</label>
    <input type="text" class="form-control" id="name" required>
    <div class="valid-feedback">
      入力されています
    </div>
    <div class="invalid-feedback">
      入力されていません
    </div>
  </div>
  <div class="form-group">
    <label for="email">メールアドレス</label>
    <input type="email" class="form-control" id="email" required>
    <div class="valid-feedback">
      正しいメールアドレスです
    </div>
    <div class="invalid-feedback">
      メールアドレスが間違っています
    </div>
  </div>
  <button class="btn btn-primary" type="submit">送信</button>
</form>

こんな感じで書くと、有効な入力の場合は .valid-feedback の部分、無効な入力の場合は .invalid-feedback の部分が表示されるとともに、フォーム部品も装飾されます。

<form>.was-validated クラスを適用することと、novalidate 属性を付けるのを忘れないようにします。novalidate 属性を付け忘れるとブラウザ側であらかじめ用意されているエラーメッセージが表示され、Bootstrap のものが適用されません。

サーバ側でバリデーションする場合

サーバ側のバリデーションを利用してフォーム画面に戻すような場合は、上記とは違う書き方になります。Laravel の Blade テンプレートだとこんな感じ。

<form novalidate>
  <div class="form-group">
    <label for="name">お名前</label>
    <input type="text" class="form-control @error('name') is-invalid @enderror" id="name" required>
    @error('name')
    <div class="invalid-feedback">
      入力されていません
    </div>
    @enderror
  </div>
  <div class="form-group">
    <label for="email">メールアドレス</label>
    <input type="email" class="form-control @error('email') is-invalid @enderror" id="email" required>
    @error('email')
    <div class="invalid-feedback">
      メールアドレスが間違っています
    </div>
    @enderror
  </div>
  <button class="btn btn-primary" type="submit">Submit form</button>
</form>

エラーメッセージを表示させたいときは、<div class="invalid-feedback"> を追加するだけでなく、同じ <div> に囲まれたフォーム部品に .is-invalid クラスを適用する必要があります。

.invalid-feedback は、少し変わった形で表示の制御がされていて、該当部分の CSS を抜き出すと

.invalid-feedback {
  display: none;
  width: 100%;
  margin-top: .25rem;
  font-size: 80%;
  color: #dc3545;
}

.was-validated :invalid ~ .invalid-feedback,
.was-validated :invalid ~ .invalid-tooltip,
.is-invalid ~ .invalid-feedback,
.is-invalid ~ .invalid-tooltip {
  display: block;
}

こんな感じになっています。A ~ B という CSS セレクタは CSS3 から導入されたもので、A 要素の後ろにある同じ階層の B 要素を選択します。このため、.is-invalid クラスを適用したフォーム部品を置いておかないと、.invalid-feedback クラスを適用したエラーメッセージが表示されないのです。

この仕組みに気づかずに、私はエラーメッセージが表示されずにしばらく悩んだのでした。。逆に言うと、

    @error('name')
    <div class="invalid-feedback">
      入力されていません
    </div>
    @enderror

の部分は、単に

    <div class="invalid-feedback">
      入力されていません
    </div>

と書いても表示されません。表示されない HTML を出力するのは無駄と考えるか、ソースの可読性を重視するか、好みの問題かもしれません。

この記事を書いた人
グッドネイバー

“ Webに悩むお客さまの「よき隣人」でありたい ” をモットーに、Web システム開発(主に Laravel)、Web マーケティング支援の仕事をしています。お仕事のご依頼・ご相談はこちらからお気軽にどうぞ。