Search code examples
ruby-on-railsformsruby-on-rails-6

form_with using a nested partial renders the form contents outside of the <form></form> elements tables, rendering content into a table row


COMPLETE REPRODUCTION APP HERE:

https://github.com/jasonfb/nested-forms-issue1

THIS HAS BEEN SUBMITTED TO THE RAILS TEAM AS A BUG

https://github.com/rails/rails/issues/38919

I am seeing some strange behavior on Rails 6.0.2.2

My haml code is like this, but I also get this result using Erb syntax.

// dashboard/skins/edit.js.erb

$(".skins-table tr[data-id=<%= @skin.id %>]").html("<%= j render partial: 'dashboard/skins/edit', locals: {skin: @skin} %>")

// dashboard/skins/_edit.haml


Edit
= skin.name

for
= skin.account.company_name

= form_with do |f|
  = render partial: "form",  locals: {skin: skin, f: f}

// dashboard/skins/_list.haml

Edit
= skin.name

for
= skin.account.company_name

= form_with model: skin, url: edit_dashboard_skin_path(skin) do |f|
  = render partial: "form",  locals: {skin: skin, f: f}

// dashboard/skins/_form.haml

= f.text_field :name
%label
  Skin Name


= f.text_area :header
%label
  Header


= f.text_area :footer
%label
  Footer


= f.text_area :native_scss
%label
  Native SCSS


= f.text_field :background_color
%label
  Background Color

= f.submit "Save", class: "btn btn-primary"

Notice that the partial is rendered within the form, thus you would expect

<form action="/dashboard/skins/2/edit" accept-charset="UTF-8" data-remote="true" method="post">
   <input type="hidden" name="_method" value="patch">
   <input type="hidden" name="authenticity_token" value="67DBVfnagSrI+DZMxfv/calLBjWq8EV2YFqMDI8oJN/ltqp1jLh3Oa64gZBRhmY25nQUsZEuFK8P/UgCLII8AA==">
   /* other form fields here */
</form>

However, Rails seems to be rendering ALL of the form content---including the hidden fields and any arbitrary text I stick inside of the form_with do block, as siblings of the form, not children of the form.

What actually happens is this:

enter image description here

Notice that the input elements that should be within the form aren't, they are siblings and appear below the closed form element.

What's interesting is that I see this effect only for the edit form, not for the create form, which displays correctly.


Solution

  • Fixed!

    My problem was that I was rendering some content into a table row <tr> content that was not wrapped inside of a <td>

    never render content into a <tr> without wrapping that content inside of a <td>

    this malformed content was breaking the form, making the contents come outside of the form as explained above