"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

はじめてLaravel6.0:チェックボックス・ラジオボタン項目を追加/入力画面(5)

入力画面でよく使う部品である、チェックボックスラジオボタンを、Laravel6.0のVIEWで使う方法です。

f:id:arakan_no_boku:20191003220222p:plain

 

はじめに

 

今回は入力画面を作成して、日付入力・SELECTを付け加えた以下の3つの記事の続きです。

arakan-pgm-ai.hatenablog.com

arakan-pgm-ai.hatenablog.com

arakan-pgm-ai.hatenablog.com

ここにチェックボックスラジオボタンを追加していこうと思えます。

 

まずは画面だけを作ってみる

 

ベース(コントローラとかルートとか)は既に作成してあるので、blade.phpファイルだけ編集して、画面表示から確認します。

まずはベタ書きで。

インライン(横並び)のラジオボタン
<div class="form-group row">
   <label for="radio01" class="col-md-4 col-form-label text-md-right">好み1</label>
   <div class="col-md-6">
      <div class="form-check form-check-inline">
         <input class="form-check-input" type="radio" id="inlineRadio01" name="radioGrp01" value="1">
         <label class="form-check-label" for="inlineRadio01">甘党</label>
      </div>
      <div class="form-check form-check-inline">
         <input class="form-check-input" type="radio" id="inlineRadio02"  name="radioGrp01" value="2" checked="checked">
         <label class="form-check-label" for="inlineRadio02">辛党</label>
      </div>
      <div class="form-check form-check-inline">
         <input class="form-check-input" type="radio" id="inlineRadio03"  name="radioGrp01" value="3" disabled>
         <label class="form-check-label" for="inlineRadio03">不明 (選択不可)</label>
      </div>
   </div>
</div>

表示するとこうなります。 

f:id:arakan_no_boku:20191104132134p:plain

 

縦並びのラジオボタン
<div class="form-group row">
   <label for="radio01" class="col-md-4 col-form-label text-md-right">好み2</label>
   <div class="col-md-6">
       <div class="form-check">
           <input class="form-check-input" type="radio" id="radio01" name="radioGrp02" value="opt1">
           <label class="form-check-label" for="radio01">あんこがギッシリ詰まった熱々のたい焼き</label>
       </div>
       <div class="form-check form-check-inline">
           <input class="form-check-input" type="radio" id="radio02" name="radioGrp02" value="opt2">
           <label class="form-check-label" for="radio02">クリームとかがはいった冷たい白たい焼き</label>
       </div>
       <div class="form-check form-check-inline">
           <input class="form-check-input" type="radio" id="radio03" name="radioGrp02" value="opt3" checked="checked">
           <label class="form-check-label" for="radio03">どちらも好きなので決められない</label>
       </div>
   </div>
</div>

表示するとこうなります。 

f:id:arakan_no_boku:20191104132407p:plain

 

チェックボックス
<div class="form-group row">
   <label for="chk01" class="col-md-4 col-form-label text-md-right">好み3</label>
   <div class="col-md-6">
       <div class="form-check">
           <input class="form-check-input" type="checkbox" id="chk01" name="chk01" value="chk01" checked="checked">
           <label class="form-check-label" for="chk01">明るくノリノリのロック調の曲が好き</label>
       </div>
       <div class="form-check form-check-inline">
           <input class="form-check-input" type="checkbox" id="chk02" name="chk02" value="chk02">
           <label class="form-check-label" for="chk02">渋いブルース風の曲が好き</label>
       </div>
       <div class="form-check form-check-inline">
           <input class="form-check-input" type="checkbox" id="chk03" name="chk03" value="chk03">
           <label class="form-check-label" for="chk03">しみじみと心にしみるバラード曲がいいな</label>
       </div>
   </div>
</div>

表示するとこうなります。

f:id:arakan_no_boku:20191104132550p:plain


これらの選択値をコントローラで受け取るとどんな値がはいっているか

 

nameを設定しているので、Requestクラスオブジェクトで、選択値を受け取れます。

public function store(Request $request)
{

    $radioGrp01 = $request->radioGrp01;
    $radioGrp02 = $request->radioGrp02;
    $chk01 = $request->chk01;
    $chk02 = $request->chk02;
    $chk03 = $request->chk03;

}

この各変数に何がはいっているか?ですが。 

$radioGrp01、$radioGrp02のラジオボタンは、選択されたValue値がはいってきます。

「<input class="form-check-input" type="radio" id="radio01" name="radioGrp02" value="opt1"> 」にあたる選択肢にチェックがついていたら、"opt1"が渡されるというわけです。

$chk01,$chk02,$chk03のチェックボックスも、チェックされているとValue値、されていないと空("")になります。

なので、空("")かどうかで、チェックされているか、されていないかを判断できるみたいです。

 

もう少し実用的なやり方にしてみる

 

べた書きでVIEWにチェックボックスラジオボタンを追加して、コントローラで値を受け取ってみました。

でも。

実際に使う時には、上記のようなべた書きは、まずしません。

マスターから表示項目を取得したり、DBに保存したものを読みだして、それを使って初期選択の状態で表示したりする必要があります。

ここからは、それをやっていきます。

とはいえ。

きっちりとDBにマスタテーブルを作って、サービス作って・・とかやると、そっちのソースのボリュームが増えて、今回の主目的である「チェックボックスラジオボタン」の使い方がぼけてしまいます。

なので、今回はサンプルとわりきって、コントローラクラスで、「DBから読み込んだ体・・」で、データをセットする方法でやってみます。

 

コントローラクラスのソースです。

 

ラジオボタンチェックボックスに渡す部分をまとめて書いてます。 

Http\Controllers\DummyController.php

 public function index()
    {
 
        $rg01Datas = [
            "op1" => "甘党",
            "op2" => "辛党",
            "op3" => "どちらでもない"
        ];
        $rg01Checked = "op2";
        
        $rg02Datas = [
            "opt1" => "あんこがギッシリ詰まった熱々のたい焼き",
            "opt2" => "クリームとかがはいった冷たい白たい焼き",
            "opt3" => "どちらも好きなので決められない"
        ];
        $rg02Checked = "opt2";
        
        $chkDatas = [
            "chk01" => "明るくノリノリのロック調の曲が好き",
            "chk02" => "渋いブルース風の曲が好き",
            "chk03" => "しみじみと心にしみるバラード曲がいいな"
        ];
        $chk01b = true;
        $chk02b = false;
        $chk03b = true;
        if ($chk01b) {
            $chkChecked["chk01"] = "checked";
        } else {
            $chkChecked["chk01"] = "";
        }
        
        if ($chk02b) {
            $chkChecked["chk02"] = "checked";
        } else {
            $chkChecked["chk02"] = "";
        }
        
        if ($chk03b) {
            $chkChecked["chk03"] = "checked";
        } else {
            $chkChecked["chk03"] = "";
        }
  
        return view('dummy', compact(
            'rg01Datas',
            'rg01Checked',
            'rg02Datas',
            'rg02Checked',
            'chkDatas',
            'chkChecked'
        ));
    }
   

ラジオボタン2種類とチェックボタン1種類です。 

チェックボックスラジオボタンがテキストボックスやSELECT(プルダウンリスト)なんかと違う点は、「選択されている」または、「チェックされている」という状態も管理しないといけないことです。

そのため、ひとつの項目に対して、

  • キーと表示項目名のペアで表示情報をわたす
  • キーとチェック状態のペアまたは選択されたコードで選択情報をわたす

の2つの配列が必要になります。

 

ラジオボタン

 

べた書きのサンプルではインライン(横展開)とデフォルト(縦並び)の2種類を書きました。

なので、コントローラでもラジオボタン向けの配列が2ペアあります。

でも、やり方自体は同じです。

なので。

ポイントの説明は、代表で「 $rg02Datas」の方だけ説明します。

まず。

「 $rg02Datas」キーは表示項目のペアの配列です。

$rg02Datas = [
    "opt1" => "あんこがギッシリ詰まった熱々のたい焼き",
    "opt2" => "クリームとかがはいった冷たい白たい焼き",
    "opt3" => "どちらも好きなので決められない"
];

あと、DBから取得する体・・はこちらです。

$rg02Checked = "opt2";

ラジオボタンは選択されている項目のコードを取得できてました。

DBにも、そのコードをそのまま保存しておくのが一番簡単です。

なので、DBから読み込んだ体・・でやるときも、単純に保存したコードを読みだして、変数にセットした想定ということになります。

 

チェックボックス

 

チェックボックスラジオボタンでは決定的な違いがあって、チェックボックスの場合は「チェックされている」「チェックされていない」の2値しか状態がないことです。

だから。

DBに状態を保存するときも、booleanカラムでの保存が効率いいです。

そうすると。

チェックボックスの「DBから読みだした体」は、以下のようになるわけです。

$chk01b = true;
$chk02b = false;
$chk03b = true; 

でも。

このTrueかFalseかの情報をそのままVIEWに渡すやり方だと、VIEW側でチェックボックスの数の増減があるときに、めんどくさいです。

やっぱり。

チェックボックスが3つ並ぶか4つ並ぶかで、いちいちVIEW側を修正するのではなく、コントローラ側だけで制御して、VIEW側では「@foreach」ループでセットするようにしたいわけです。

ということで。

自分は以下のようにして、チェックあり、なしの配列を作ってVIEW側に渡してます。

if ($chk01b) {
    $chkChecked["chk01"] = "checked";
} else {
    $chkChecked["chk01"] = "";

そうすると。

チェックボックスのキーと表示文字列のペアも配列で持つことになります。

$chkDatas = [
    "chk01" => "明るくノリノリのロック調の曲が好き",
    "chk02" => "渋いブルース風の曲が好き",
    "chk03" => "しみじみと心にしみるバラード曲がいいな"
];

こうする時、注意すべきポイントが一つあります。

それは、キーにあたる「chk01」などの名前が1つのページ内で重複しないようにしたほうがよいことです。

なぜかというと。

LaravelではSubmitした時のチェックボックスの値を、nameに設定した名前をキーにして受け取ります。

なので、ループを回す今回のような方法でチェックボックスを動的につくる場合、nameを固定値にしておくと具合が悪いわけです。

そんな時、上記のキーの値を「name」に流用するという手段をとると良いので、極力、ユニークにしとくと後が楽・・というわけです。 

 

VIEW(Blade側)の定義の仕方

 

Bladeテンプレートで、コントローラクラスから渡された配列変数を使って、ループで展開するソースです。

 

ラジオボタン

 

resources\views\dummy.blade.php

<div class="form-group row">
   <label for="radioGrp01" class="col-md-4 col-form-label text-md-right">好み1</label>
   <div class="col-md-6">
      @foreach($rg01Datas as $rkey => $rval)
      <div class="form-check form-check-inline">
         <input class="form-check-input" type="radio" id="radioGrp01" name="radioGrp01" value="{{$rkey}}"
           @if(empty(old()) and $rkey == $rg01Checked) checked="checked"
           @elseif($rkey == old('radioGrp01'))) checked="checked"
           @endif
         >
         <label class="form-check-label" for="{{$rkey}}">{{$rval}}</label>
      </div>
      @endforeach
  </div>
</div>

<div class="form-group row">
   <label for="radioGrp02" class="col-md-4 col-form-label text-md-right">好み2</label>
   <div class="col-md-6">
      @foreach($rg02Datas as $r2key => $r2val)
      <div class="form-check">
         <input class="form-check-input" type="radio" id="radioGrp02" name="radioGrp02" value="{{$r2key}}"
            @if(empty(old()) and $r2key == $rg02Checked) checked="checked"
            @elseif($r2key == old('radioGrp02'))) checked="checked"
            @endif
         >
         <label class="form-check-label" for="{{$r2key}}">{{$r2val}}</label>
      </div>
      @endforeach
   </div>
</div>

ポイントを補足します。

LaravelのVIEWの場合、

  • 初期表示でコントローラでセットした状態を反映させる
  • バリデーションエラーで戻った場合に入力中の状態を復元する

 のそれぞれに考慮が必要です。

まず前者が

@if(empty(old()) and $r2key == $rg02Checked) checked="checked"

の部分です。

empty(old())で初期表示であることを確認し、かつ、$er02Checkedには、コントローラクラスで選択中のコードがはいっていますので、それと一致するキーがあった場合に「checked」にします。

後者が

@elseif($r2key == old('radioGrp02'))) checked="checked"

 の部分で、「old('radioGrp02')」でバリデーション時に選択中だったキーの値があいっていますので、それと一致するキーの時に「checked」にします。

 

チェックボックス

 

resources\views\dummy.blade.php

<div class="form-group row">
   <label for="chk01" class="col-md-4 col-form-label text-md-right">好み3</label>
   <div class="col-md-6">
      @foreach($chkDatas as $ckey => $cval)
      <div class="form-check">
         <input class="form-check-input" type="checkbox" id="chk01" name="{{$ckey}}" value="{{$ckey}}"
            @if(empty(old()) and $chkChecked[$ckey] == 'checked') checked="checked"
            @elseif($ckey == old($ckey))) checked="checked"
            @endif
         >
         <label class="form-check-label" for="{{$ckey}}">{{$cval}}</label>
     </div>
     @endforeach
  </div>
</div>

ポイントはチェックボックスの場合も同じです。 

初期表示でコントローラでセットした状態を反映させる場合が

@if(empty(old()) and $chkChecked[$ckey] == 'checked') checked="checked"

です。

コントローラクラスで「$chkChecked[$ckey] 」に、チェックあり(True)の場合に「checked」の文字列をしこんでいるので、それと比較してます。

バリデーションエラーで戻った場合に入力中の状態を復元する場合が

@elseif($ckey == old($ckey))) checked="checked"

 です。

これはラジオボタンと同じで、チェックされていれば「old($ckey)」にValueの値が入っている前提で比較して、一致していれば「checked」にしています。

ただ、チェックボックスの場合、Submit時にnameに設定された名前で情報を取得しますので、ユニークになるよう、nameにもvalueと同じキーの値をセットしてます。

<input class="form-check-input" type="checkbox" id="chk01" name="{{$ckey}}" value="{{$ckey}}"

この辺がラジオボタンとの違いですね。

 

さて実行してみます

 

MariaDBをたちあげて、ビルトインサーバーを起動します。

php artisan serve

 そのうえで「http://localhost:8000/dummy」で実行します。

f:id:arakan_no_boku:20191108232059p:plain

コントローラクラスでセットした選択肢が、ちゃんと選択されています。

これでとりあえず、初期選択と違うものに変更して、バリデーションエラーになるような入力で登録ボタンを押します。

f:id:arakan_no_boku:20191108232420p:plain

バリデーションエラーで戻った時に、ちゃんと変更した選択状態が復元されてます。

OKみたいですね。

今回はこんなところで。

ではでは。