Current section
Files
Jump to
Current section
Files
lib/live_admin/components/resource/form/search_select.ex
defmodule LiveAdmin.Components.Container.Form.SearchSelect do
use Phoenix.LiveComponent
use Phoenix.HTML
import LiveAdmin, only: [record_label: 2, trans: 1]
alias Phoenix.LiveView.JS
alias LiveAdmin.Resource
@impl true
def mount(socket) do
{:ok, assign(socket, :options, [])}
end
@impl true
def update(assigns = %{form: form, field: field}, socket) do
socket =
socket
|> assign(assigns)
|> assign_selected_option(input_value(form, field))
{:ok, socket}
end
@impl true
def update(assigns, socket) do
{:ok, assign(socket, assigns)}
end
@impl true
def render(assigns = %{disabled: true}) do
~H"""
<div>
<span class="resource__action--disabled">
<%= if @selected_option do %>
<%= record_label(@selected_option, @resource) %>
<% else %>
<%= trans("None") %>
<% end %>
</span>
</div>
"""
end
@impl true
def render(assigns) do
~H"""
<div>
<div class="resource__action--drop">
<%= hidden_input(@form, @field,
disabled: @disabled,
value: if(@selected_option, do: @selected_option.id)
) %>
<%= if @selected_option do %>
<a
href="#"
phx-click={JS.push("select", value: %{id: nil}, target: @myself, page_loading: true)}
class="resource__action--btn"
>
<%= record_label(@selected_option, @resource) %>
</a>
<% else %>
<%= text_input(:search, :select,
id: input_id(@form, @field) <> "search_select",
disabled: @disabled,
placeholder: trans("Search"),
phx_focus: "load_options",
phx_keyup: "load_options",
phx_target: @myself,
phx_debounce: 200,
autocomplete: "off"
) %>
<% end %>
<%= unless @selected_option do %>
<nav>
<ul>
<%= if Enum.empty?(@options) do %>
<li><%= trans("No options") %></li>
<% end %>
<%= for option <- @options, option.id != input_value(@form, @field) do %>
<li>
<a
href="#"
phx-click={
JS.push("select", value: %{id: option.id}, target: @myself, page_loading: true)
}
>
<%= record_label(option, @resource) %>
</a>
</li>
<% end %>
</ul>
</nav>
<% end %>
</div>
</div>
"""
end
@impl true
def handle_event(
"load_options",
%{"value" => q},
socket = %{assigns: %{resource: resource, session: session}}
) do
options =
resource
|> Resource.list([search: q, prefix: socket.assigns.prefix], session, socket.assigns.repo)
|> elem(0)
{:noreply, assign(socket, :options, options)}
end
def handle_event("select", %{"id" => id}, socket) do
socket =
socket
|> assign_selected_option(id)
|> push_event("change", %{})
{:noreply, socket}
end
defp assign_selected_option(socket, id) when id in [nil, ""],
do: assign(socket, :selected_option, nil)
defp assign_selected_option(
socket = %{assigns: %{selected_option: %{id: selected_option_id}}},
id
)
when selected_option_id == id,
do: socket
defp assign_selected_option(socket, id),
do:
assign(
socket,
:selected_option,
Resource.find!(id, socket.assigns.resource, socket.assigns.prefix, socket.assigns.repo)
)
end