Shawn Wilson Shawn Wilson - 3 months ago 19
jQuery Question

Rails 5 Bootstrap 3 Modal Layout issue

I am using Rails 5 and Bootstrap 3 to build out an app, In this app I want Admins to be able to create and update users, to do so the create and update forms are held in bootstrap 3 Modals.

The modal is working, forms are working however there is a layout issue. The modal body and footer seem to be running together. I have checked to ensure all the divs have been closed off and they arrear to be, however the top div of the modal and its closing div dont seem to recognize each other.. I think the problem is with the modal #id when I remove the modal id it seems to work fine, whick leaves me to believe its the ruby in the id. (see below) is there any way to hack this out so it works?


Opening Modal Div with Ruby as part of the ID


<div class="modal fade" id="<%= "update_user#{user.id}" %>" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
...
</div>



Full Modal Code


<div class="modal fade" id="<%= "update_user#{user.id}" %>" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel"><text id="pv_text_grn">PATROL</text><text id="pv_text_gry">VAULT</text> <i class="fa fa-pencil-square-o" aria-hidden="true"></i> Update <%= user.f_name %> <%= user.l_name %></h4>
</div>
<div class="modal-body">
<%= form_for(user, :method => :put, remote: true) do |f| %>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div class="row">
<div class="col-xs-12">
<div class="field">
<%= f.label :email, "Email" %><br />
<%= f.email_field :email, :class => 'form-control' %>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-6">
<div class="field">
<%= f.label :password %>
<%= f.password_field :password, autocomplete: "off", :class => 'form-control', :placeholder => '* * * * * *' %>
</div>
</div>
<div class="col-xs-12 col-sm-6">
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off", :class => 'form-control', :placeholder => '* * * * * *' %>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-6">
<div class="field">
<%= f.label :f_name, "First Name" %><br />
<%= f.text_field :f_name, disabled: true, :class => 'form-control' %>
</div>
</div>
<div class="col-xs-12 col-sm-6">
<div class="field">
<%= f.label :l_name, "Last Name" %>
<%= f.text_field :l_name, disabled: true, :class => 'form-control' %>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="field">
<%= f.label :primary_tel, "Telephone" %>
<%= f.text_field :primary_tel, :class => 'form-control' %>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<div class="field">
<%= f.label :role_id %><br />
<%= collection_select(:user, :role_id, Role.all, :id, :name, {prompt: true}) %>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<%= f.submit "Update User", :class => 'btn btn-primary' %>
</div>
<% end %>
</div>
</div>
</div>



Image Of Modal


enter image description here

You can see that the dividing line that should be at the footer is now for some reason at the top just below the email label.

Any assistance here would be a great help.

-> The reason I am using the user.id in the modal id is to create unique modal id's as there are several users.

Answer

You need to remove the wrapping <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12"> tag.

I've also refactored the structure. You shouldn't have to wrap any inputs with .col-xs-12, this is default for inputs. You can wrap inputs in .form-group for bottom spacing.

<div class="modal fade" id="<%= "update_user#{user.id}" %>" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="myModalLabel"><text id="pv_text_grn">PATROL</text><text id="pv_text_gry">VAULT</text> <i class="fa fa-pencil-square-o" aria-hidden="true"></i> Update <%= user.f_name %> <%= user.l_name %></h4>
      </div>
      <div class="modal-body">
        <%= form_for(user, :method => :put, remote: true) do |f| %>
          <div class="field">
            <%= f.label :email, "Email" %><br />
            <%= f.email_field :email, :class => 'form-control' %>
          </div>
          <div class="row">
            <div class="col-xs-12 col-sm-6">
              <div class="field">
                <%= f.label :password %>
                <%= f.password_field :password, autocomplete: "off", :class => 'form-control', :placeholder => '* * * * * *' %>
              </div>
            </div>
            <div class="col-xs-12 col-sm-6">
              <div class="field">
                <%= f.label :password_confirmation %><br />
                <%= f.password_field :password_confirmation, autocomplete: "off", :class => 'form-control', :placeholder => '* * * * * *' %>
              </div>
            </div>
          </div>
          <div class="row">
            <div class="col-xs-12 col-sm-6">
              <div class="field">
                <%= f.label :f_name, "First Name" %><br />
                <%= f.text_field :f_name, disabled: true, :class => 'form-control' %>
              </div>
            </div>
            <div class="col-xs-12 col-sm-6">
              <div class="field">
                <%= f.label :l_name, "Last Name" %>
                <%= f.text_field :l_name, disabled: true, :class => 'form-control' %>
              </div>
            </div>
          </div>
          <div class="field">
            <%= f.label :primary_tel, "Telephone" %>
            <%= f.text_field :primary_tel, :class => 'form-control' %>
          </div>
          <div class="row">
            <div class="col-xs-6">
              <div class="field">
                <%= f.label :role_id %><br />
                <%= collection_select(:user, :role_id, Role.all, :id, :name, {prompt: true}) %>
              </div>
            </div>
          </div>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
          <%= f.submit "Update User", :class => 'btn btn-primary' %>
        </div>
      <% end %>
    </div>
  </div>
</div>

Also, you should consider using dom_id for your tag ids. It will prefix the id with the correct verb based on if the object. (edit or new) And follows the rails naming convention pattern.

# Update
dom_id(Post.find(45), :edit) # => "edit_post_45"
dom_id(Post.new, :custom)    # => "custom_post"
# New
dom_id(Post.find(45))       # => "post_45"
dom_id(Post.new)            # => "new_post"

http://api.rubyonrails.org/classes/ActionView/RecordIdentifier.html

You can use it with content_tag or embed in the html tag.

<%= content_tag :div, id: dom_id(user) do %>...<% end %>
<div id="<%= dom_id user %>">...</div>

PS: There is also dom_class.

Comments