Hello everybody,
Iam new to Phoenix Components, I have tried form
inside LiveView and it was amazing, but I have an issue :
form
is created by Phoenix.Component.to_form/2
which transform a changeset
to a form
and we can use <.input type = "text" field = {@form[:somefield]}
to represent a form’s field and the user’s data will be found in handle_event("submit", %{"user" => data}, socket)
after submitting the form, Okay that’s fine.
But how about other inputs types than <.input type = "text">
?
For example if we want to implement a template where someone can Signup a new account :
he has some <.input type = "text">
s like username
, email
, password
and he has to choose from a “Radio Button” between Man and Woman and he has to choose a date of birth from “Scroll Lists”…
So how we can implement that ? and the most important how we can retrieve user’s entered data in handle_event("submit"....)
?
I have searched about and I couldn’t find docs or examples, so I will be thankful for your answers.
With the new core components like <.input ...>
and <.modal>
, they’re just functions that are defined and documented within your Phoenix app in lib/hello_web/components/core_components.ex
.
So while the type
attribute defaults to "text"
, it also accepts a whole bunch of other values including "radio"
as well as "date"
.
attr :type, :string,
default: "text",
values: ~w(checkbox color date datetime-local email file hidden month number password
range radio search select tel text textarea time url week)
Thank you @codeanpeace,
Considering we have used no-text type for an <.input>
for example “Multi Select List”, how we can retrieve user’s input in handle_event/3
after submitting ?
Hi @Sidi_Mohammed , kindly asking if you can elaborate more or provide more context on your question, perhaps even a simple example of what you are trying to archieve?
Just want to understand what you mean here:
Are you trying to implement a Multi Select input?
Exactly @jmnda, I want to implement a list which the user can select multi values, how we can implement that please ? and how we can retrieve the selected values in handle_event/3
when submitting the form ?
Use can pass a multiple
attribute to your input
with options
to select, for example:
<.input field={@form[:tags]} type="select" multiple options={[:item_1, :item_2, :item_3]} label="Tags />
As @Joep suggested, you can search on the forum, alternatively you can look at this guide, or checkout this library
Here’s how you can discover it for yourself!
# assuming your multi-select is within the existing user form
def handle_event("submit", %{"user" => data}, socket) do
IO.inspect(data)
# and optionally when running `iex -S mix phx.server`
require IEx; IEx.pry
...
{:noreply, socket}
end
# or more generally
def handle_event("submit", params, socket) do
IO.inspect(params)
...
end
I sword I have thinked the same thing to show the data’s map
and see what’s happening , Iam just waiting until turn on my computer,
thank you a lot again @codeanpeace
Is this what you’re looking for?
The options bit are a bit confusing to add if you don’t know how already. I asked someone the other day how to do it and ended up with this.
Add @options with your options in the formcomponent.ex and add :options to the socket.
@options [
{"Newest", "newest"},
{"Oldest", "oldest"},
{"Popular", "popular"},
{"Least Viewed", "least viewed"},
{"Most Popular", "most popular"}
]
@impl true
def update(%{example: example} = assigns, socket) do
changeset = Example.change_example(example)
{:ok,
socket
|> assign(assigns)
|> assign(:changeset, changeset)
|> assign(:options, @options)
}
end
Your inpute type then just needs to be set to “select” and options are obviously the :options in the socket.
:example is whatever your database field is named
<.input field={f[:example]} type="select" options={@options} />
Hope this is what you were after.
edit: No idea why I added so many random popular options lol
Thank you @GazeIntoTheAbyss, this is so helpful, I understand the idea, that means :example
field will be associated with multiple values in handle_event/3
which are selected by the user
Just last thing, as @codeanpeace has suggested, IO.inspect/1
is required to see what was happening behind scenes because we can’t make any expectation about, for example the Component Function implementation for both <.input field = {@form[:username]} type = "text">
and <.input field = {@form[:username]} type = "radio">
is here but for text
we will find user’s entry in handle_event("submit", %{"user" => %{"username" => username....)
but for radio
we will find it in handle_event("submit", %{"user" => params, "name_of_radio_button" => username}....)
.
This behaviour shows that a radio button
will not be treated as form
’s field
, so I have to handle errors manually, for example if we want to force the user to select one value from all radio button
s and if he didn’ t an error
shows : “you must select a username”, how we can do that ?
Without prepending the .
in <.input>
, you won’t actually be calling the input/1
function in your core components that appropriately nests the input field within the form.
@codeanpeace, Iam sorry it was just a written mistake, of course I have used <.input>
not <input>
.
now I just want to know how to show errors manually for an <.input>
which will not be handled as form
’s field