DEV Community

Cover image for [TIL] Reusable LiveView.JS commands with JS.exec
Dung Nguyen for OnPoint Vietnam

Posted on

3

[TIL] Reusable LiveView.JS commands with JS.exec

This article was originally posted on https://bluzky.github.io/2023-07-12-til-reusable-liveview-js-commands-with-js-exec/

In this post I will build a simple dropdown for demo purpose. Not fully functional as a real dropdown :D.

1. Duplicated code

<div
  class="relative inline-block m-10"
  id="my-dropdown"
  phx-mounted={@open && (JS.show(to: "#my-dropdown .dropdown-content") |> JS.add_class("bg-blue-300", to: "#my-dropdown .dropdown-btn"))}
>
  <div
    class="dropdown-btn border border-gray-100 px-4 py-2 rounded-lg bg-gray-700 text-white inline-block cursor-pointer"
    phx-click={JS.show(to: "#my-dropdown .dropdown-content") |> JS.add_class("bg-blue-300", to: "#my-dropdown .dropdown-btn")}
  >
    Toggle button
  </div>
  <div class="dropdown-content absolute hidden bottom-0 left-0 translate-y-full w-[275px] bg-slate-50 rounded-lg border border-slate-200 shadow-md py-5">
    <div class="border-b hover:bg-slate-100 px-5 py-2">Item 1</div>
    <div class="border-b hover:bg-slate-100 px-5 py-2">Item 2</div>
    <div class="border-b hover:bg-slate-100 px-5 py-2">Item 3</div>
    <div class="border-b hover:bg-slate-100 px-5 py-2">Item 4</div>
    <div class="border-b hover:bg-slate-100 px-5 py-2">Item 5</div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

2. Writing a function

To avoid duplicated JS code, you can write a function in LiveView component

def open_dropdown(id) do
    [to: "##{id} .dropdown-content"]
    |> JS.show()
    |> JS.add_class("bg-blue-300", to: "##{id} .dropdown-btn")
end
Enter fullscreen mode Exit fullscreen mode

and update your template

<div
  class="relative inline-block m-10"
  id="my-dropdown"
  phx-mounted={@open && open_dropdown("my-dropdown")}
>
  <div
    class="dropdown-btn border border-gray-100 px-4 py-2 rounded-lg bg-gray-700 text-white inline-block cursor-pointer"
    phx-click={open_dropdown("my-dropdown")}
  >
    Toggle button
  </div>
  <div class="dropdown-content absolute hidden bottom-0 left-0 translate-y-full w-[275px] bg-slate-50 rounded-lg border border-slate-200 shadow-md py-5">
    <!-- Your dropdown content -->
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

This way you write code in 2 separated modules and you have to switch between them to understand how it works.

3. Reuse code with JS.exec

JS.exec's document says:

Executes JS commands located in element attributes.

The followed example make me think that it only support some special attributes like phx-remote and phx-* attributes. Recently I found that it could be any attribute name.

The example above can be rewrite:

<div
  class="relative inline-block m-10"
  id="my-dropdown"
  action-open-dropdown={
    JS.show(to: "#my-dropdown .dropdown-content")
    |> JS.add_class("bg-blue-300", to: "#my-dropdown .dropdown-btn")
  }
  phx-mounted={@open && JS.exec("action-open-dropdown")}
>
  <div
    class="dropdown-btn border border-gray-100 px-4 py-2 rounded-lg bg-gray-700 text-white inline-block cursor-pointer"
    phx-click={JS.exec("action-open-dropdown", to: "#my-dropdown")}
  >
    Toggle button
  </div>
  <div class="dropdown-content absolute hidden bottom-0 left-0 translate-y-full w-[275px] bg-slate-50 rounded-lg border border-slate-200 shadow-md py-5">
    <!-- Your dropdown content -->
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

This way you don't have to switch between files to get full implementation logic.

Image of Datadog

How to Diagram Your Cloud Architecture

Cloud architecture diagrams provide critical visibility into the resources in your environment and how they’re connected. In our latest eBook, AWS Solution Architects Jason Mimick and James Wenzel walk through best practices on how to build effective and professional diagrams.

Download the Free eBook

Top comments (0)