_method param added to a form?

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.

1 Like

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".

5 Likes

That’s what I needed, although @LostKobrakai 's reply just made me learn something new. Many thanks to both of you!