西村 祐真
@variant3a
Livewire + Alpine.jsでdraggableなモーダルを作る
2022-11-03
views: 1284
経緯
Alpine.jsでドラッグして移動できるモーダルを作成しようと思ったが、誰も作っていないので自分で作成した。Alpine流行ってくれ...
ただ、Alpine.jsは基本的にプレーンなjavascriptが書ければ1から作成するのもそれほど難しくない。(難しいのはLivewireとの同期)
環境
- Laravel 9
- Livewire 2
- Alpine.js
ソースコード
フロントエンド
<div class="modal-position-wrap fixed"
x-data="{
mouse: { x: 0, y: 0 },
modalStyle: $wire.entangle('modal_window'),
isModalShow: $wire.entangle('is_modal_show')
}"
x-show="isModalShow" x-cloak x-transition>
<div class="modal"
x-ref="modalEl"
x-bind:style="modalStyle">
<div class="modal-header" draggable="true"
x-on:dragstart="
mouse.x = $refs.modalEl.offsetLeft - event.pageX;
mouse.y = $refs.modalEl.offsetTop - event.pageY;
event.dataTransfer.setDragImage(document.createElement('div'), 0, 0);
"
x-on:drag="
if (!event.x && !event.y) return;
$refs.modalEl.style.setProperty('left', event.pageX + mouse.x + 'px');
$refs.modalEl.style.setProperty('top', event.pageY + mouse.y + 'px');
"
x-on:dragend="
$wire.set('modal_window.left', event.pageX + mouse.x + 'px');
$wire.set('modal_window.top', event.pageY + mouse.y + 'px');
mouse.x = mouse.y = 0;">
<span class="modal-title">
Modal Title
</span>
<button type="button" class="modal-close" x-on:click="isModalShow = !isModalShow">
x
</button>
</div>
<div class="modal-content">
this is modal content area.
<input type="text" wire:model="input_model" class="modal-input">
</div>
<div class="modal-footer">
<button type="button" class="modal-action" x-on:click="isModalShow = !isModalShow">
Save(Close)
</button>
</div>
</div>
</div>
重要部分の解説
LivewireとAlpine.jsでの状態共有
基本的にはモーダルの中にinputが無いとか、モーダル表示中にバックエンド側と通信するようなことがなければLivewireにはモーダルの位置情報の共有はしなくて良いが、このソースのようにmodalが開いた状態でLivewireのモデルと通信するような場合は必須。(Livewireはbladeの静的ファイルを参照して差分更新するから)
コード中では、変数 modalStyle
と modalShow
でモーダルの位置情報と開閉状態を $wire.entangle
で逐一双方向通信している。
ちなみに変数 modalStyle
はデータセットしていないので $wire.entangle
でなくても良いんじゃないの?と思ったが、 $wire.modal_window
だとモーダル位置がリセットされてしまう。 要検証。
モーダルの位置情報のセット
モーダルの位置を操作するに当たり、element objectを取得する必要があるが、Alpineでは x-ref="hoge"
で取得することができる。
elementを取得できたところで、コード中の x-on:dragstart
, x-on:drag
, x-on:dragend
でそれぞれやることを記述している。
x-ref="modalEl"
でモーダルを取得x-on:dragstart
でモーダルの初期位置を取得してマウス位置情報として保存、モーダルの残像も消す。x-on:drag
でドラッグ中のマウス位置を逐一モーダルに反映させるx-on:drag
でドラッグ終了直後のモーダル位置をLivewireに共有
バックエンド
class Modal extends Component
{
public $modal_window;
public $is_modal_show;
public $input_model;
public function mount()
{
$this->is_modal_show = true;
$this->modal_window['left'] = '0px';
$this->modal_window['top'] = '0px';
}
}
重要部分
mount()
でマウントされた際の初期データを入れておこう。
2022-11-03
views: 1284
most viewed
Laradockを利用したLaravel環境構築
@variant3a
2022-06-09
views: 369
BrowserSyncを使おう
@variant3a
2022-06-09
views: 291
Office365UserコネクタのSearchUserV2の制限
@variant3a
2022-07-14
views: 320
Laravelのルーティング順による404エラーの対処法
@variant3a
2022-07-16
views: 648
「"仮想DOMは速い"という神話を完全に終わりにしよう」
@variant3a
2022-07-19
views: 454