In various code samples, I see different ways to create a form in a .heex template.
What is the difference between using the following:
<%= form_for @changeset, "/to_path", ...other_opts, fn f -> %>
...
<% end %>
<%= f = form_for @changeset, "to_path, ...other_opts %>
...
<% end %>
<.form let={f} for={@changeset} action={"to_path"} ...other_opts>
...
</.form>
Is there a best practice, or is it just up to the preferences of the developer?
1 Like
I found some answers in the Phoenix.HTML docs:
-
<%= f = form_for @changeset ... %>
is now deprecated. Use <%= form_for @changeset ... %>
instead.
-
<.form>
is a “function component”, in the context of Phoenix LiveViews.
This leads me to a follow-up question: If I don’t use LiveViews, should I still use <.form>
?
1 Like
You’re right about the difference. According to the LiveView docs, <.form>
is just a wrapper around form_for
and should generally be preferred if you’re using HEEx templates (including on deadviews). Just remember to give the action
attribute!
See Phoenix.LiveView.Helpers documentation under “Outside LiveView”
7 Likes
And for the ones of us running Phoenix.LiveView pre-0.18
(e.g., 0.17.14
) there is also the “Outside LiveView” example under the Phoenix.LiveView.Helpers.form/1
documentation.
I know this thread is old, but I was struggling with the same question, so I’ll post the answer in case anyone else comes across this thread like I did.
tl;dr:
form_for
should no longer be used and will eventually be removed from Phoenix.
- In LiveView, use
<.form for={@form}>
where @form
is a Phoenix.HTML.Form
struct (generally created using to_form
). Don’t use :let
.
- Outside of LiveView, you can also pass a changeset or map to
for
, and it’ll be converted to a Form
which can be captured with :let
. (This approach is also technically possible in a LiveView, but it’s discouraged because it makes change tracking less efficient.)
The second and third points are made clear in the docs for form/1. The first point was confirmed to me by none other than Chris McCord; I wrote about it here:
4 Likes
Correct. .form is the way to go, form_for will forever exist for backwards compatibility, f = form_for
is deprecated and should be rewritten.
4 Likes