Closed edisonywh closed 3 years ago
This is what an example Suggestion component will look like:
defmodule SlickWeb.NewsletterSuggestionComponent do
use SlickWeb, :live_component
def mount(socket) do
socket =
socket
|> assign(:suggestions, [])
|> assign(:picked, nil)
{:ok, socket}
end
def render(assigns) do
~L"""
<input type="text" value="<%= @picked || @value %>" phx-debounce="500" phx-target="<%= @myself %>" phx-keyup="suggest" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md transition">
<%= if @suggestions != [] do %>
<div class="relative">
<div class="absolute left-0 right-0 rounded-md border border-gray-50 shadow-lg py-2 bg-white">
<%= for {id, name} <- @suggestions do %>
<div
phx-target="<%= @myself %>"
phx-click="pick"
phx-value-id="<%= id %>"
phx-value-name ="<%= name %>"
class="cursor-pointer p-2 hover:bg-gray-200 focus:bg-gray-200">
<%= name %>
</div>
<% end %>
</div>
</div>
<% end %>
"""
end
def handle_event("suggest", %{"value" => ""}, socket) do
socket = socket |> assign(:suggestions, [])
send self(), {:pick, {:newsletter_id, value: nil}}
{:noreply, socket}
end
def handle_event("suggest", %{"value" => value}, socket) do
require Ecto.Query
suggestions =
Slick.Newsletters.list_newsletters(query: value)
|> Ecto.Query.limit(4)
|> Ecto.Query.select([:id, :name])
|> Slick.Repo.all()
|> Enum.map(&({&1.id, &1.name}))
socket = socket |> assign(:suggestions, suggestions)
{:noreply, socket}
end
def handle_event("pick", %{"id" => id, "name" => name}, socket) do
socket =
socket
|> assign(:picked, name)
|> assign(:suggestions, [])
send self(), {:pick, {:newsletter_id, value: id}}
{:noreply, socket}
end
end
This works right now, but I'm not sure if this is a good use case to allow users to add custom hidden_input to form
. Thoughts?
This commit enables user to pass in custom LiveComponent for more complex form field.
User do it like so:
This creates a stateful LiveComponent that can update your form input values.
This works with a few assumption:
:id
phx-keyup
, becausephx-change
doesn't work outside ofform
.<form>
, because HTML5 spec mandates that you cannot have nested form tags.In your Suggestion component, you can show user the available suggestions, then when they click, you should handle the event and then let the FormComponent know. You do this by:
This will forward the request to the parent LiveView, which will then broadcast it to the FormComponent. For example, say you are editing a schema called Listing. It has a field called
newsletter_id
(belongs_to), and you want to have suggestions when user is typing so they can search in-line. You would then send it as:This would create a
hidden_input
on your<form>
, which would update:newsletter_id
to be4
.Fixes #2