mitgliederverwaltung/lib/mv_web/live/components/search_bar_component.ex

81 lines
2.2 KiB
Elixir

defmodule MvWeb.Components.SearchBarComponent do
@moduledoc """
Provides the SearchBar Live-Component.
- uses the DaisyUI search input field
- sends search_changed event to parent live view with a query
"""
use MvWeb, :live_component
@impl true
def update(%{query: query}, socket) do
socket =
socket
|> assign_new(:query, fn -> query || "" end)
|> assign_new(:placeholder, fn -> gettext("Search...") end)
{:ok, socket}
end
@impl true
def render(assigns) do
~H"""
<form phx-submit="search" phx-target={@myself} class="flex" role="search" aria-label="Search">
<label class="input">
<svg
class="h-[1em] opacity-50"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
aria-hidden="true"
>
<g
stroke-linejoin="round"
stroke-linecap="round"
stroke-width="2.5"
fill="none"
stroke="currentColor"
>
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.3-4.3"></path>
</g>
</svg>
<input
type="search"
placeholder={@placeholder}
value={@query}
name="query"
data-testid="search-input"
phx-change="search"
phx-target={@myself}
phx-debounce="300"
/>
<button
:if={@query not in [nil, ""]}
type="button"
phx-click="clear_search"
phx-target={@myself}
data-testid="search-clear"
aria-label={gettext("Clear search")}
class="opacity-50 hover:opacity-100 cursor-pointer"
>
<.icon name="hero-x-mark" class="h-[1em]" />
</button>
</label>
</form>
"""
end
@impl true
# Function to handle the search
def handle_event("search", %{"query" => q}, socket) do
# Forward a high level message to the parent
send(self(), {:search_changed, q})
{:noreply, assign(socket, :query, q)}
end
# Clears the query and resets the result set to the unfiltered list (§1.3).
def handle_event("clear_search", _params, socket) do
send(self(), {:search_changed, ""})
{:noreply, assign(socket, :query, "")}
end
end