Victor Schubert’s personal page

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.