2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Laravel6】Bootstrap4で横並びにしたラジオボタンのバリデーションメッセージを表示する時の落とし穴

Last updated at Posted at 2021-02-22

概要

Laravelアプリでコンテンツ登録時にBootstrapで作成したラジオボタンのバリデーションメッセージが表示されない事態に陥りました。

本記事ではその解決方法の一例を紹介します。

※Laravelアプリで発生しましたが、原因はBootstrapだったのでLaravel特有なものではないです。

環境

$ composer -V
Composer version 1.10.20 2021-01-27 15:41:06

$ php artisan --version
Laravel Framework 6.20.16

前提

バリデーションメッセージは各入力項目の下に分けて表示させる。
(「カテゴリーは必ず指定してください。」がバリデーションメッセージです)

スクリーンショット 2021-02-22 7.39.07.png

よくLaravel教材で採用されているのは、画面上部に全てのバリデーションメッセージを箇条書きで表示する方法で以下のコード。
(公式ドキュメントより)

<!-- /resources/views/post/create.blade.php -->

<h1>ポスト作成</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<!-- ポスト作成フォーム -->

今回はこちらのコード(例)を採用します。
(こちらも公式ドキュメントより)

<!-- /resources/views/post/create.blade.php -->

<label for="title">Post Title</label>

<input id="title" type="text" class="@error('title') is-invalid @enderror">

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

Bootstrapで横並びにしたラジオボタンのバリデーションメッセージを表示する時の落とし穴の解決方法

解決済みのコード

create.balde.php
{{--  --}}

<div class="form-group mb-4">
    <p for="exampleInputPassword1">カテゴリー<span class="text-danger">()</span></p>
    {{-- ラジオボタン  --}}
    <div class="form-check form-check-inline is-invalid">
        <input class="form-check-input form-check-inline is-invalid " type="radio" name="category_id" id="category1" value="1" >
        <label class="form-check-label" for="category1">Laravel</label>
    </div>                        
    <div class="form-check form-check-inline is-invalid">
        <input class="form-check-input form-check-inline is-invalid " type="radio" name="category_id" id="category2" value="2" >
        <label class="form-check-label" for="category2">PHP</label>
    </div>                        
    <div class="form-check form-check-inline is-invalid">
        <input class="form-check-input form-check-inline is-invalid" type="radio" name="category_id" id="category3" value="3" >
        <label class="form-check-label" for="category3">Docker</label>
    </div>                        
    <div class="form-check form-check-inline is-invalid">
        <input class="form-check-input form-check-inline is-invalid" type="radio" name="category_id" id="category4" value="4" >
        <label class="form-check-label" for="category4">web基礎</label>
    </div>
    {{-- バリデーションメッセージ --}}
    <span class="invalid-feedback" role="alert">
        <strong>カテゴリーは必ず指定してください</strong>
    </span>
</div>
{{--  --}}

落とし穴にハマった時のコード

create.balde.php
{{--  --}}

<div class="form-group mb-4">
    <p for="exampleInputPassword1">カテゴリー<span class="text-danger">()</span></p>
    {{-- ラジオボタン  --}}
    <div class="form-check form-check-inline">
        <input class="form-check-input form-check-inline is-invalid" type="radio" name="category_id" id="category1" value="1" >
        <label class="form-check-label" for="category1">Laravel</label>
    </div>                        
    <div class="form-check form-check-inline">
        <input class="form-check-input form-check-inline is-invalid" type="radio" name="category_id" id="category2" value="2" >
        <label class="form-check-label" for="category2">PHP</label>
    </div>                        
    <div class="form-check form-check-inline">
        <input class="form-check-input form-check-inline is-invalid" type="radio" name="category_id" id="category3" value="3" >
        <label class="form-check-label" for="category3">Docker</label>
    </div>                        
    <div class="form-check form-check-inline">
        <input class="form-check-input form-check-inline is-invalid" type="radio" name="category_id" id="category4" value="4" >
        <label class="form-check-label" for="category4">web基礎</label>
    </div>
    {{-- バリデーションメッセージ --}}
    <span class="invalid-feedback" role="alert">
         <strong>カテゴリーは必ず指定してください</strong>
    </span>
</div>
{{--  --}}

これだとバリデーションメッセージが表示されません。

スクリーンショット 2021-02-22 7.48.30.png

違いと解決理由

違い

1つ1つのラジオボタン(inputタグのtype=radio)の親のクラスにdivタグにis-invalidがつけているかついていないか

バリデーションメッセージが表示される

<div class="form-check form-check-inline is-invalid">

バリデーションメッセージが表示されない

<div class="form-check form-check-inline>

解決理由

バリデーションエラー時に入力フォームを赤くして、メッセージを表示させるには以下のルールがあったのですが、シンプルにそれを満たしていなかっただけでした。

  • ラジオボタンのinputタグのクラスにis-invalidがついている
  • バリデーションメッセージを表示するDOMの兄弟要素(同じ階層)のタグのクラスにそれぞれis-invalidinvalid-feedbackがついている

こんな感じでinputタグとspanタグを兄弟要素にするとバリデーションメッセージが表示されますが、レイアウトがうまくできませんでした。。

    {{--  --}}
    <input class="form-check-input form-check-inline is-invalid" type="radio" name="category_id" id="category4" value="4" >
    <label class="form-check-label" for="category4">web基礎</label>
    {{-- バリデーションメッセージ --}}
    <span class="invalid-feedback" role="alert">
        <strong>カテゴリーは必ず指定してください</strong>
    </span>

補足

実際のコードはLaravelで

  • @errorディレクティブでバリデーションメッセージの有無を判定
  • ラジオボタンの選択肢データをDBにマスターデータとして保持して取得する(カテゴリーの追加を楽にするため)

をしているため実際のコードは以下の通りです。

Viewファイル

create.blade.php
{{--  --}}
<div class="form-group mb-4">
    <p for="exampleInputPassword1">カテゴリー<span class="text-danger">()</span></p>
    {{-- ラジオボタン  --}}
    @foreach ($categoryForRadioButton as $index => $categoryName)
        <div class="form-check form-check-inline @error('category_id') is-invalid @enderror">
            <input class="form-check-input form-check-inline @error('category_id') is-invalid @enderror" type="radio" name="category_id" id="category{{ $index }}" value="{{ $index }}" {{ old('category_id') == $index ? 'checked': '' }}>
            <label class="form-check-label" for="category{{ $index }}">{{ $categoryName }}</label>
        </div>                        
    @endforeach
    {{-- バリデーションメッセージ --}}
    @error('category_id')
        <span class="invalid-feedback" role="alert">
            <strong>{{ $message }}</strong>
        </span>
    @enderror
</div>
{{--  --}}

ラジオボタンの選択肢取得用

Category.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    /**
     * ラジオボタン用の配列データを作成
     *
     * @return array
     */
    public function getAll(): array
    {
        $categoryForRadioButton = [];

        $allCategories = $this->all();
        foreach ($allCategories as $index => $category) {
            $categoryForRadioButton[$index + 1] = $category->name;
        }
        return $categoryForRadioButton;
    }
}

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?