チェックボックスはオフの時に値をpostしません。
登録のみなら構わないのですが、編集時はオフの時に値をpostされないと、チェック状態が外せなくなります。
#hiddenを埋め込む
いくつか方法はある(プログラム側でなんとかするとか、jsでなんとかするとか)のですが、
今回はhiddenを埋め込む方法でやってみます。
<input name="cb1" type="hidden" value="0">
<input name="cb1" type="checkbox" value="1">
このようにチェックボックスの前にhiddenで0を埋め込んでおくと
- チェックボックスがオンの時はvalueの1がpostされる
- チェックボックスがオフの時はhiddenの0がpostされる
のです。
#formヘルパーで実装
ネットで検索すると
formヘルパーを使った
{{ Form::hidden('cb1', 0) }}
{{ Form::checkbox('cb1', 1, $data['cb1'] ?? '') }}
のような書き方が散見されます。
確かにhiddenもcheckboxもこれで配置されますが、
この方法はひとつ落とし穴があります。
Form::hiddenはoldの影響を受けるのです。
#検証
このようなフォームがあって
チェックボックスには先ほどの
{{ Form::hidden('cb1', 0) }}
{{ Form::checkbox('cb1', 1, $data['cb1'] ?? '') }}
という記述をしているとします。
テキストにはフォームリクエストバリデーションで必須を指定しています。
では、チェックボックスをオンにして、テキストには何も入力せずにpostしてみましょう。
テキストのバリデーションエラーで入力画面に戻りました。
この状況でhiddenの値がどうなっているかというと…
チェックボックスをオンにしたため、cb1=1としてpostされ、
old('cb1')は1になります。
バリデーションエラーで戻ってきた入力画面では、Form::hiddenはこの値を使用して
valueの値を変更します。
というわけで、formヘルパーでhiddenを埋め込むと
valueを0に固定できません。
まぁ、
<input name="cb1" type="hidden" value="0">
{{ Form::checkbox('cb1', 1, $data['cb1'] ?? '') }}
と書けば解決するんですが、
あまりテンションの上がらない書き方です。
「チェックしたままpostしてバリデーションエラーで戻されてからチェックを外す」
という状況でしか問題にならないから別にええやないか、とも言えますが、
やっぱりあまりテンションは上がらない感じになります。
#ないなら作る
LaravelのFormヘルパーはマクロを自作できます。
というわけで
チェックボックスの前に自動でhiddenの値を埋め込んでくれる
Form::booleanboxを自作します。
$ php artisan make:provider FormMacroServiceProvider
class FormMacroServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
require app_path().'/Libs/FormMacro.php';
}
}
'providers' => [
App\Providers\FormMacroServiceProvider::class,
],
\Form::macro("booleanbox", function($name, $value = 1, $checked = null, $options = array()){
return $this->toHtmlString("<input type=\"hidden\" name=\"{$name}\" value=\"0\">". \Form::checkbox($name, $value, $checked, $options));
});
あとは
{{ Form::booleanbox('cb1', 1, $data['cb1'] ?? '') }}
と書けば
Form::checkboxと
全く同じように使えるようになります。
#とはいえ
新規案件でしたら
vue / react なんかで
ページ遷移とかoldとかを気にしない作りにしてしまうのが
一番気持ちいいとは思います。
古いプロジェクトの修正をする必要がある場合なんかにどうぞ。
これならForm::checkboxを一括置換するだけで済むので。