6

I'm having one heck of an issue working out how to do this. I have 2 forms that need to be displayed next to each other but you can't embed forms, I got around this by just putting the 2nd form after the first one.

However, rails is ignoring my <% end %> tag for the 2nd form and it is auto-closing the 2nd form before it needs to be closed. This is making my form not work.

Here's the view with some bits omitted for brevity.

<div class="row">
  <div class="col-md-3">
    <div class="well">
      <%= render "shared/some_form", url_path: foo_path %>
      <%= form_tag some_other_path, method: :delete, id: "form_bulk_action", role: "form" do %>
      <div id="bulk_action_group">
        <div class="form-group">
          <%= label_tag "perform_bulk_action", "For each checked item" %>
          <%= select_tag "perform_bulk_action", options_for_select([ ["Delete", "destroy"] ]), class: "form-control" %>
        </div>
        <%= button_tag id: "foo" %>
      </div>
    </div>
  </div>
  <div class="col-md-9">
    <table class="table table-condensed table-hover">
      <thead>
        <tr>
          <th><%= check_box_tag :check_all_data_rows, "", false %></th>
        </tr>
      </thead>
      <tbody>
        <% @foo.each do |foo| %>
          <tr>
            <td><%= check_box_tag "bulk_ids[]", foo.id, false, %></td>
          </tr>
        <% end %>
      </tbody>
    </table>
  </div>
</div>
<% end %>

The partial that is loading some_form is the first form. The beginning and end of that form happens inside of the partial.

The second form is the form_tag. As you can see from the html markup we have a sidebar on the left and the main contents on the right being loaded in a table.

The idea of the 2nd form is it allows you to check off rows and then perform a bulk action on the checked off items. Similar to how you might mark 15 e-mails in gmail and then delete them.

The problem is rails is ignoring the <% end %> at the bottom of that code snippet and instead it's injecting a </form> right after the button with an id: foo.

This is causing the bulk_ids value to always be nil because at that point the form is already closed and they are not part of the form. The crazy thing is it only fails when you goto the page from another page (ie. turbolinks). It works when you do a full load of the page, however I think the main issue is the premature closing of the </form> tag.

How can I set this all up so the forms are not embedded and the 2nd form closes all the way at the bottom of the table while still using the form helpers?

AntelopeSalad
  • 1,736
  • 1
  • 16
  • 27
  • How do you know Rails is adding a tag? Your HTML is not balanced, and your <% end %> is too low. I think if Chrome, for example, saw this, then it would "forgive" the unbalanced tags, and insert a where it belonged. Then if you, for example, used Context Menu -> Inspect Element to view the code, you would see Chrome's internal element database, NOT its raw source. You should use View Source to see what the webserver sent (because ERB, AFAIK, will NOT balance tags for you). Better yet, you should also use automated tests with validating assertions. – Phlip Nov 02 '13 at 05:15
  • I saw the tag in a spot where I certainly didn't place it. I guess Chrome added it then? I do have model/functional tests and they all pass because the bulk_ids value is a hard coded array. I'm not really sure how I can reorganize my html to make this all work. – AntelopeSalad Nov 02 '13 at 12:39
  • You need to answer how you "saw" the tag. AFAIK the only way to see one is Chrome's Inspect Element, if the tag otherwise does not exist. What does View Source say, and what do your automated tests say? – Phlip Nov 02 '13 at 17:43
  • It shows up in Chrome's inspect element. In the view source it's at the bottom. My automated tests say nothing because I don't have end to end tests written for that functionality, only model/functional tests where the bulk id value is stubbed. – AntelopeSalad Nov 02 '13 at 18:33
  • At least you _have_ tests! But write functional tests with real model objects, not stubs. But I don't understand where the extra comes from, because if you generate broken HTML Rails with faithfully transmit it. Or so I thought... – Phlip Nov 03 '13 at 16:14
  • I am using the real model's functionality in the test. The bulk_id in this case is being transmitted through the controller on the live site and the params[:bulk_id] property is being sent from the form to the controller. In my tests I just pass [1,2,3] to the bulk methods in the model. Anyways yeah, I still don't know how to get the form to visually render the way I would like while conforming to html rules with form placement. – AntelopeSalad Nov 03 '13 at 20:29
  • I had the same problem. In my case I had a lonely `
    ` tag without the `
    ` close tag and the `form_tag` and the `end` in differents `div`. A complete disaster.
    – itziki Apr 09 '14 at 10:16

2 Answers2

0

Your root problem appears to be forms are both actions and rectangles. So you need a little rectangle inside a bigger one, each with its own, different action. A CSS expert might know how to write a <form style="display:inline" ...> such that one form can flow around another, without enforcing a rectangular shape.

Phlip
  • 5,253
  • 5
  • 32
  • 48
0

I believe the problem is that the form originates with the render shared/some_form call that is inside the , but the code to close the form is outside that div and after a table. If you move the start of the form to above all the divs shown here and have all the divs and tables reside inside the form, then it should work.

My understanding is that a form is not meant to operate correctly half inside another element and thus a form should either be within or outside other elements, not partially.

Here is a little more information about forms and tables (and divs): Form inside a table

Community
  • 1
  • 1
Ryan
  • 10,798
  • 11
  • 46
  • 60