今回は、VueJSのコンポーネントの話ではありません。Inertiaの話でもありません。Laravelのブレードコンポーネントの話です。使い始めると結構いいものです。
デモ
こんな入力画面あるとします。
もともとのブレードは、こんな感じです。
... <div class="card-body"> <form method="POST" action="{{ route('register') }}"> @csrf <div class="row mb-3"> <label for="email" class="col-md-4 col-form-label text-md-end">メールアドレス</label> <div class="col-md-6"> <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus> @error('email') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="row mb-0"> <div class="col-md-6 offset-md-4"> <button type="submit" class="btn btn-primary"> 登録 </button> </div> </div> </form> </div> ...
今度は、コンポーネントを使用した、ブレードファイルの中身を見てみましょう。
... <div class="card-body"> <x-form action="{{ route('register') }}"> <div class="row mb-3"> <x-label name="email">メールアドレス</x-label> <div class="col-md-6"> <x-input type="email" name="email" required autocomplete="email" /> </div> </div> <div class="row mb-0"> <div class="col-md-6 offset-md-4"> <x-button type="submit" level="primary">登録</x-button> </div> </div> </x-form> </div> ...
見た目、とてもシンプルになりました。しかし、見慣れないHTMLタグがx-form, x-label, x-input, x-buttonと4つありますね。
もちろんそれらがコンポーネントなのですが、どうやってそれらのタグが利用できるようになるのでしょうか?
コンポーネントの作成
コンポーネントの作成には、2つ方法があり、app/View/Componentsのディレクトリ下にクラスファイルを作成する方法と、resources/views/componentsに匿名コンポーネントを作成する方法があります。ここでは使いやすい後者を紹介します。
先のデモの4つのコンポーネントは、以下のようなファイルに定義されています。
resources/views/components ├── button.blade.php ├── form.blade.php ├── input.blade.php └── label.blade.php
button.blade.phpというコンポーネントブレードファイルを作成すれば、それだけで、他のブレードファイルで、<x-button>
のタグとして使用可能になります。
コンポーネントの定義
まずは、一番外側のx-formの定義です。
@props([ 'method' => 'POST', 'action', ]) @php $method = Str::upper($method); @endphp <form method="{{ $method === 'GET' ? 'GET' : 'POST' }}" action="{{ $action }}" {{ $attributes }}> @csrf @if (! in_array($method, ['GET', 'POST'])) @method($method) @endif {{ $slot }} </form>
御覧のように、通常のブレードファイルと同じように、@if
や@php
が使えます。しかし、@props
は見たことありませんね。
@props
では、コンポーネントを使用するブレードから、コンポーネントにデータを渡すための変数の宣言と初期化をします。
ここでは、methodとactionの変数がありますが
<x-form action="{{ route('register') }}">
では、actionにしかデータを渡していません。しかし、@props
においてmethodのデフォルトはPOSTと指定されているので、実際に出力されるHTMLは、以下のように初期化されます。
<form method="POST" action="http://localhost/register"> <input type="hidden" name="_token" value="8GdTncryczY6s2gkHCMFYJyRlvab2tkLbVp9iRUE"> .. </form>
もう1つ重要なのは、{{ $slot }}
です。
そこの部分には、<x-form>と</x-form>のタグの間の値がすべて渡されます。
x-labelでも同様に{{ $slot }}
を使います。
@props([ 'name', ]) <label for="{{ $name }}" class="col-md-4 col-form-label text-md-end">{{ $slot }}</label>
x-buttonも同様です。
@props([ 'type' => 'button', 'level' => 'default', ]) <button type="{{ $type }}" {{ $attributes->class("btn btn-$level")}}>{{ $slot }}</button>
@attributes->class
は、既存のclassの属性に引数のclassをマージします。
例えば、
<x-button type="submit" class="m-2" level="primary">登録</x-button>
なら、
<button type="submit" class="btn btn-primary m-2">登録</button>
となります。
最後に、x-inputの定義です。
@props([ 'type' => 'text', 'name', 'value' => null, ]) <input type="{{ $type }}" name="{{ $name }}" value="{{ old($name, $value) }}" @error($name) {{ $attributes->class('form-control is-invalid') }} @else {{ $attributes->class('form-control') }} @enderror /> @error($name) <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror
以下のようにコンポーネントで定義していない属性(requiredやautocomplete)も渡していますが、
<x-input type="email" name="email" required autocomplete="email" />
これらは、そのまま最終のHTMLに渡されます。
<input type="email" name="email" value="" class="form-control" required autocomplete="email">メルマガ購読の申し込みはこちらから。