# The Toggling UI Element with LiveView

Here’s Sophie DeBenedetto, co-author of [_Programming Phoenix LiveView_](https://pragprog.com/titles/liveview/programming-phoenix-liveview/) with a deep dive into building a toggling UI element with LiveView’s `JS.toggle` command.

LiveView empowers developers to be more productive by keeping your mind focused on the server while building rich interactive UIs. Recently, LiveView has improved its ability to manage client-side interactions through [JS commands](https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.JS.html). This post will guide you through building a toggle feature using `JS.toggle`.

## The Problem

You want to toggle the appearance of content in response to user interactions. For example, showing/hiding a search form when clicking the “search” icon. Without JS commands, you’d need to send events to the server to manage the UI state.

## The Solution

The `Phoenix.LiveView.JS` module provides functionality to invoke client-side operations in response to LiveView events. It abstracts common JS interactions like showing/hiding content, adding/removing classes, and setting CSS attributes.

## Example: Toggling a Form

We'll look at an example to create a toggling feature for a hidden form:

```elixir
# lib/live_library_web/live/book_live/search_component.html.heex

<.form
  let={f}
  for={@search_changeset}
  id="book-search-form"
  phx-submit="search"
  phx-target={@myself}
  class={@search_class} >
```

To make the form hidden on page load, we’ll use CSS:

```css
/* assets/css/app.css */

#book-search-form {
 display: none;
}
```

Now, let’s make it toggle using `Phoenix.LiveView.JS.toggle/1`:

```elixir
def icon(assigns) do
  ~H"""
  <i phx-click={JS.toggle(to: "#book-search-form")} class="bi bi-search"></i>
  """
end
```

Now, clicking the search icon will toggle the form's visibility.

## LiveView JS Commands Under the Hood

The `JS.toggle/1` function generates a `Phoenix.LiveView.JS` struct for toggling:

```elixir
%Phoenix.LiveView.JS{
  ops: [
    [
    "toggle",
      %{
        display: nil,
        ins: [[], [], []],
        outs: [[], [], []],
        time: 200,
        to: "#book-search-form"
      }
    ]
  ]
}
```

LiveView binds the `phx-click` event to the appropriate JS actions when rendering the template.

## Trigger Client- and Server-Side Interactions Together

You can chain JS commands to push messages to the server while toggling the search form on the client:

```elixir
def icon(assigns) do
  ~H"""
  <i phx-click={JS.push("toggle_book_search", target: @target) |> JS.toggle(to: "#book-search-form")} class="bi bi-search"></i>
  """
end
```

This allows the search form to toggle and URL updates without forcing a page reload. The event handler for `"toggle_book_search"` can manage the URL changes conveniently:

```elixir
def handle_event("toggle_book_search", _value, socket) do
  if socket.assigns.search_class == "show" do
    {:noreply, push_patch(socket, to: "/books")}
  else
    {:noreply, push_patch(socket, to: "/books?search")}
  end
end
```

This approach fosters a seamless user experience where interactions feel fluid without unnecessary reloads.

## JS Commands Give Us Simple and Powerful Client-Side Interactions

LiveView abstracts common JS functionalities, allowing you to implement features without writing JavaScript. Explore more in the [docs](https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.JS.html).

---
