Under what circumstances a _method field is added to a form, so that Plug.MethodOverride
can use it to turn a POST into, for example, a PUT? Sometimes a hidden input field is automatically generated, other times I need to add <input name="_method" type="hidden" value="put" />
to the form. I’m clearly missing something…
I would say it’s added whenever your form uses a method other than POST or GET. Web forms can only send data using those two methods (<form>: The Form element - HTML: HyperText Markup Language | MDN), other methods have to be simulated.
IIRC form_for
decides on a method based on the action
of the changeset it’s passed (put
for update
vs plain post
for insert
) - can you be more specific about how you’re rendering these forms?
Here is how I render the form:
<%= form_for @changeset, Routes.some_path(@conn, :update, abc), fn _f -> %>
<input name="_method" type="hidden" value="put" />
<%= submit("update", class: "btn") %>
<% end %>
if <input name="_method" type="hidden" value="put" />
is removed, no _method
will be sent in the POST, independently of the action passed to the changeset (I tried bot update
and insert
).
Any idea why?
The action in the changeset is irrelevant, you need to pass the :method
option to form_for: Phoenix.HTML.Form — Phoenix.HTML v2.14.2
Quoting the docs:
:method
- the HTTP method. If the method is not “get” nor “post”, an input tag with name_method
is generated along-side the form tag. Defaults to “post”.
And you don’t need to manually render the _method_
hidden field
The action is indeed irrelevant, but the schema metadata on a struct used for a changeset is used to infer the method for the form if not explicitly supplied. If the metadata state is :built
(or anything else) is uses "post"
, if it’s :loaded
it infers "put"
.
That’s what I needed, although @LostKobrakai 's reply just made me learn something new. Many thanks to both of you!