Livewireのフロントエンド的利用において重要なアクション
本連載は、LaravelのLivewireとInertiaを利用して、フロントエンド的な画面作成方法を紹介しています。前回のLivewireの基礎的な使い方に続いて、今回は、Livewireのよりフロントエンド的な使い方を紹介します。
本連載のサンプルデータは、GitHubから参照できます。
イベントに応じた処理を行うアクション
今回紹介するサンプルは、図1の画面です。

前回の図5と同じように、カクテル名がリスト表示されています。このカクテル名をクリックすると、前回は画面が遷移し、前回の図6のように、その詳細情報が表示されるものでした。
一方、今回はカクテル名をクリックすると、画面は遷移せず、図2のように同じ画面内に詳細情報が表示されます。また、表示されたカクテル詳細情報セクションの[閉じる]ボタンをクリックすると、詳細情報セクションが消えて、図1の画面に戻ります。

これは、カクテル名のクリック、[閉じる]ボタンのクリック、それぞれのクリックイベントに応じて、画面が変化するように処理が組まれているからです。このように、各イベントに応じての処理を、Livewireではアクション(Action)と言います。
クリックイベントアクションの呼び出しはwire:click
図1や図2の画面のコンポーネント名をCocktailListとするならば、コンポーネントビューファイルはリスト1のようになります。
<div> <h1>カクテル管理</h1> <section> <h2>カクテルリスト</h2> <ul> @foreach($listData as $cocktailInList) <li wire:key="{{$cocktailInList->id}}"><a wire:click="showDetail({{$cocktailInList->id}})">{{$cocktailInList->name}}</a></li> // (1) @endforeach </ul> <p><a href="/cocktailAdd">カクテルの追加はこちら</a></p> </section> @if($detailSection) // (2) <section> <h2>{{$cocktail->name}}の詳細</h2> <dl> : </dl> <button wire:click="closeDetail">閉じる</button> // (3) </section> @endif </div>
リスト1の(1)のカクテル名を囲んでいるaタグ内、および(3)の[閉じる]ボタンのbuttonタグ内に記述されたwire:clickという属性が、クリックイベントに対応したアクションを実行するための記述です。これを、イベントリスナ(Event Listener)と言います。
イベントリスナの属性値として任意の文字列を記述することができ、その文字列を名前とするメソッドを、コンポーネントクラスに定義することで、イベントに対応した処理が実行されることになります。つまり、wire:clickの属性値は、メソッド名を表します。
(1)のように引数を渡すこともできます。(1)では、カクテルのID値を引数として渡しています。これらのメソッドのコード例は、次の項で紹介します。
なお、ここではwire:clickと、クリックイベントのイベントリスナを紹介しましたが、サブミットイベントに対応するwire:submitやマウスエンターイベントに対応するwire:mouseenterなど、wire:に続く記述は、ブラウザがサポートしているあらゆるイベントを利用できます。
アクションの処理はコンポーネントクラスのメソッド
イベントリスナに対応した処理、つまりアクションの処理は、コンポーネントクラスにメソッドとして実装します。
リスト1では、イベントリスナの属性値として(1)のshowDetail、(3)のcloseDetailが記述されているので、コンポーネントクラスであるCocktailListには、これらのメソッドが定義されて、リスト2のようになります。
class CocktailList extends Component { public Collection $listData; // (1) public bool $detailSection = false; // (2) public Cocktail $cocktail; // (3) public function mount() { $this->listData = Cocktail::all(); // (4) } public function showDetail($id) // (5) { $this->detailSection = true; // (6) $this->cocktail = Cocktail::find($id); // (7) } public function closeDetail() // (8) { $this->detailSection = false; // (9) } public function render() { return view("livewire.cocktail-list"); } }
リスト2では(5)がリスト1の(1)に対応するメソッドであり、(8)がリスト1の(3)に対応するメソッドです。このように、単にイベントリスナの属性値と同名のメソッドを定義するだけです。その際、リスト1の(1)のように引数の受け渡しが必要な場合は、リスト2の(5)のように引数定義を行います。
これらアクションのメソッド内の処理を解説する前に、先に他のコードを説明しておきます。まず、リスト2の(1)の$listDataがカクテルリストのデータであり、画面表示時にCocktailモデルを利用してデータベースから全データを取得してきています。それが(4)です。これにより、図1のように、画面にカクテルリストが表示されます。
では(2)の$detailSectionは何かと言うと、リスト1では(2)で利用されており、カクテルの詳細情報を表示するセクションの表示・非表示の切り替えのための変数です。この$detailSectionは初期値がfalseであり、falseの場合は、カクテルの詳細情報が表示されるsectionタグ全体がレンダリングされません。逆に、この値をtrueにすることで、sectionタグがレンダリングされます。
この仕組みを利用し、カクテルリストがクリックされたときのアクションのメソッドである(5)のshowDetail()内では、(6)のように、$detailSectionをtrueに変更しています。このように単にプロパティの値を変更するだけで画面表示が変わり、まさにフロントエンド的な処理内容となっています。
同様に、リスト2の(7)では、(5)のshowDetail()の引数として受け取ったカクテルIDをもとに、データベースから該当カクテルデータを取得しています。その取得したCocktailオブジェクトを(3)のプロパティに代入するだけで、画面に表示されるようになります。
リスト1の(3)の[閉じる]ボタンの処理も、リスト2の(9)のように単にプロパティの$detailSectionの値をfalseにしているだけです。これで、リスト1の(2)のifが作用し、カクテル詳細表示のsectionタグがレンダリングされなくなり、結果、閉じたような処理となります。