Forms don’t nest
Working on a side project of mine, for which I decided to use Ruby on Rails with a Javascript-free front-end, I was recently surprised by a behaviour of HTML forms. I wished to make a page that could edit some record, with two submit buttons next to one another, to submit the changes or delete the record, respectively. To that effect, I wished to get the following markup.
<form action="/record" method="post"> <input type="hidden" name="id" value="42"> <input type="hidden" name="_method" value="patch"> <input type="text" name="description"> <input type="submit"> <form action="/record" method="post"> <input type="hidden" name="id" value="42"> <input type="hidden" name="_method" value="delete"> <input type="submit"> </form> </form>
The
_method
hidden input is a Rails-specific thing: it will override the request method as perceived by the server, so that a POST can be interpreted by the server as a PATCH or as a DELETE.
My assumption was that I would actually have nested form, and that activating one of the submit buttons would submit the nearest form parent. What I got instead, was a nasty bug which had both the “update” and “delete” button delete the record… A little bit of research and troubleshooting later, I learned that forms must not be nested, and that browsers actually strip out the nested forms’ tags, so that what I could eventually see in the browser’s dev tools was this.
<form action="/record" method="post"> <input type="hidden" name="id" value="42"> <input type="hidden" name="_method" value="patch"> <input type="text" name="description"> <input type="submit"> <input type="hidden" name="id" value="42"> <input type="hidden" name="_method" value="delete"> <input type="submit"> </form>
Coupled to the fact that when multiple hidden inputs share a name
the browser will use the last one defined, any request went away
with _method
set to delete
, and the record
would get deleted.