LoginSignup
10
1

Phoenix LiveView で mouseenter 、 mouseleave イベントを扱う

Last updated at Posted at 2023-12-24

はじめに

Elixir の Web フレームワーク Phoenix LiveView では phx-click などのバインディングによって Web 上のイベントを Elixir に伝えます

しかし、マウスカーソルが要素に入ったときのイベント mouseenter や要素から出たときのイベント mouseleave はバインディングに存在しません

少し工夫が必要になります

Elixir forum の以下の提案を参考に実装しました

どういうときに必要か

そもそも、単に Web 上の見た目を変えるだけなから TailwindCSS の hover: を使うだけで十分です

また、ちょっとした動作の制御であれば Alpine.js で x-on:mouseenterx-on:mouseleave で事足ります

無駄にややこしくする必要はないので、基本的には TailwindCSS と Alpine.js だけで実装してしまう方がいいでしょう

Elixir 側での制御、ソケットで管理している値に介入する必要がある場合のみ、以下の実装が必要になります

実装

マウスイベントを拾いたい要素にフックを紐づけます

イベントで渡したい引数(%{"some_key" => "some_value"})があれば data- で持たせておきます

Heex

<div
  id="some-element"
  phx-hook="MouseHook"
  data-some_key="some_value"
/>

フックでは mounted の中で mouseentermouseleave のイベントリスナーを追加します

pushEvent の第2引数に event.target.datasetdata- で指定した引数が入っています

JS

const MouseHook = {
  mounted () {
    this.el.addEventListener('mouseenter', event => {
      this.pushEvent('mouseenter', event.target.dataset)
    })
    this.el.addEventListener('mouseleave', event => {
      this.pushEvent('mouseleave', event.target.dataset)
    })
  }
}

Elixir では pushEvent で JS から来たイベントを handle_event で受け取ります

Elixir

...
  @impl true
  def handle_event("mouseenter", %{"some_key" => some_value}, socket) do
    ...
    {:noreply, socket}
  end

  @impl true
  def handle_event("card_mouseleave", %{"some_key" => some_value}, socket) do
    ...
    {:noreply, socket}
  end
...

まとめ

基本的に Hooks を通した JS との連携でなんとでもなります

ただし、 Elixir でやるべきことと JS でやるべきことは上手く線引きしないと、どんどんややこしい実装になるので注意しましょう

基本的には JS を多用しすぎない方がいいです

10
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
1