🦓

[Laravel]AlpineJS+Livewireでモーダルコンポーネントを作る

2023/10/25に公開

はじめに

Livewire 3.xからAlpineJSをインクルードされるようになったのでAlpineJS+Livewireでモーダルコンポーネントを作っていきます。

https://alpinejs.dev/
https://livewire.laravel.com/docs/installation

環境

PHP 8.x
Laravel 10.x
MySQL 8.x
Livewire 3.x

tl;dr

Livewire 3.xをインストールされたことを前提で進めます。

  1. モーダルコンポーネントを作成する
  2. モーダルを定義する
  3. モーダルを使う

モーダルコンポーネントを作成する

php artisan make:component Modal
   INFO  Component [app/View/Components/Modal.php] created successfully.  

モーダルを定義する

x-dataディレクティブを使ってモーダルを定義していきます。
x-data は Alpine.js で使用されるディレクティブの1つで、特定のコンポーネントや要素にデータをバインドするために使用されます。
x-dataにより、その要素内でデータの追跡、変更、操作が行えるようになります。

https://alpinejs.dev/directives/data

ボタンをクリックしてモーダルを開く

resources/views/components/modal.blade.php
<x-button x-on:click="$dispatch('open-modal', 'モーダル名')">
  モーダル
</x-button>

$dispatchを使ってopen-modalイベントを発火させます。

https://alpinejs.dev/magics/dispatch

イベントopen-modalを定義する

showfalseの場合モーダルを非表示、trueの場合表示するように定義します。

resources/views/components/modal.blade.php
<div
    x-data = "{ show: false }" // モーダルを非表示
    x-on:open-modal.window="$event.detail == '{{ $name }}' ? show = true : null" // モーダル名があれば表示する、ない場合非表示
    x-on:close="show = false" // closeイベント
    x-on:keydown.escape.window="show = false" // escapeキーをクリックしたら非表示
    x-show="show" // モーダルの表示
    class=""
    style="display: {{ $show ? 'block' : 'none' }};"
>
...
</div>

x-showはDOM要素の表示と非表示を制御するためのディレクティブです。
https://alpinejs.dev/directives/show

クローズボタンをクリックしてモーダルを閉じる

$dispatchを使ってcloseイベントを発火させます。

resources/views/components/modal.blade.php
<x-close-button x-on:click="$dispatch('close')">
    // クローズボタン
</x-close-button>

モーダルコンテンツ以外をクリックしてモーダルを閉じる

背景をクリックしてモーダルを閉じるように背景にクリックレスポンスを追加します。

resources/views/components/modal.blade.php
<div
    x-show="show"
    class=""
    x-on:click="show = false"
>
  // モーダル背景
    <div class="absolute inset-0 bg-gray-400 opacity-75"></div>
</div>

モーダルを使う

@propsディレクティブを使ってモーダルコンポーネントのプロパティを定義します。
@propsは、Bladeビューでコンポーネントを使用する際に、コンポーネントにデータを渡すための仕組みです。

resources/views/components/modal.blade.php
@props([
    'name', // モーダル名
    'show' => false // デフォルトでは非表示
])

https://laravel.com/docs/10.x/blade#data-properties-attributes

投稿一覧にある投稿をクリックしたら内容をモーダルに表示されるように実装します。

app/livewire/PostList.php
<?php

namespace App\Http\Livewire;

use LivewireUI\Modal\ModalComponent;

class PostList extends Component
{
	public function viewPost(Post $post){
		$this->dispatch('open-modal', name: 'view-post');
	}
}
resources/views/livewire/post-list.blade.php
@foreach ($this->posts as $post)
...
 <x-button wire.click="viewPost({{ $post }})">
	投稿を見る
 </x-button>
@endforeach

 <x-modal name="view-post">
 ...
    <x-close-button>
      閉じる
    </x-close-button>
 </x-modal>

終わりに

簡単ですがAlpineJS+Livewireでのモーダルコンポーネントでした。
Livewire公式のモーダルコンポーネントもあるのでそちらをインストールして使うこともできます!
https://github.com/wire-elements/modal

Discussion