Rails Form in Bootstrap Modal - ruby-on-rails

I'm trying to put a rails form in a bootstrap modal dialog. I'd like to use the modal-footer to hold the cancel/submit buttons, but this doesn't seem to work inside the form tag.
<div class="modal-body">
<%= simple_form_for [#state, #search] do |f| %>
<!-- long form here -->
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
<%= f.button :submit, :class => 'btn btn-primary' %>
</div>
<% end %>
</div>

That's because you are putting the footer inside the body. Use this way instead:
<%= simple_form_for [#state, #search] do |f| %>
<div class="modal-body">
<!-- long form here -->
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
<%= f.button :submit, :class => 'btn btn-primary' %>
</div>
<% end %>

Related

Problems with Modal in Rails opening the same object

I'm maintaining an older Rails 3.2.22 app and I'm trying to add a modal to pop up with a simple form to add a note.
Here is my view (cut down for readability)
<% #assigned.each do |call| %>
<%= link_to "Notes", '#ajax-modal', data: { toggle: "modal", target: "#note-modal" }, class: 'btn btn-small btn-inverse' %>
<%= render 'layouts/note_modal', :call => call %>
<% end %>
Here is my modal app/views/layouts/_note_modal.html.erb
<div id="note-modal" class="modal hide fade" tabindex="-1">
<div class='modal-header'>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="modal-title"><%= call.incident_number %> Notes</h3>
</div>
<div class='modal-body'>
<div class="modal-body-content">
<%= form_for(#note, url: call_note_calls_path, html: {class: "form-inline"}) do |f| %>
<%= f.text_field :message, :maxlength => 255 %>
<%= f.hidden_field :call_id, value: call.id %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.button "Add Note", class: 'btn btn-info btn-small', data: {disable_with: "<i class='icon-spinner'></i>Posting..."} %>
<% end %></div>
<div class="ajax-loader">
</div>
</div>
<div class='modal-footer'>
<button type="button" data-dismiss="modal" class="btn">Close</button>
</div>
</div>
When I load the page and there are several calls I click on the notes link, the partial renders in a modal and I can submit a note. The problem is if I have 10 calls on the screen no matter which notes link I click on it adds a note to the first call on the screen.
Am I passing locals incorrectly? I know this code is inside of the block so it should pull the call object and pass it as a local to the partial in the modal but it's not.
Any help is greatly appreciated.
I think the issue is that you render the modal each time for a note but they all have the same id. So you are always opening the first modal. Actually IMHO you just need to render the modal once and pass the note_id via an data attribute on the link which triggers the modal. So basically configure the modal via the caller.
I was able to figure this out on my own and still render the partial within the loop by calling an index as part of the target ID for the modal. Working code below.
<% #assigned.each_with_index do |call, index| %>
<%= link_to "Notes", '#note-modal', data: {toggle: "modal", target: "#note-modal#{index}" }, class: 'btn btn-small btn-inverse' %>
<%= render 'layouts/note_modal', call: call, index: index %>
<% end %>
<div id="note-modal<%= index %>" class="modal hide fade" tabindex="-1">
<div class='modal-header'>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="modal-title"><%= call.incident_number %> Notes</h3>
</div>
<div class='modal-body'>
<div class="modal-body-content">
<%= form_for(#note, url: call_note_calls_path, html: {class: "form-inline"}) do |f| %>
<%= f.text_field :message, :maxlength => 255 %>
<%= f.hidden_field :call_id, value: call.id %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.button "Add Note", class: 'btn btn-info btn-small', data: {disable_with: "<i class='icon-spinner'></i>Posting..."} %>
<% end %></div>
<% call.notes.each do |n| %>
<li><%= n.message %> added by <%= n.user.username %></li>
<% end %>
<div class="ajax-loader">
</div>
</div>
<div class='modal-footer'>
<button type="button" data-dismiss="modal" class="btn">Close</button>
</div>
</div>

carrierwave AJAX upload with remotipart

In my rails4 I would like to submit a form via AJAX that has a file uploaded via carrierwave. As far as I know it can be done via remotipart, but can't figure it out how I can do that. (Remotipart installed properly since it's working with refile gem that I also use in the app.)
With the current code below the form gets submitted according to the logs and it says the create.js.erb is rendered, but the code in the create.js.erb file never runs.
Rendered posts/create.js.erb (387.0ms)
What should I do?
form
<%= form_for #post, remote: true, method: :post, :html => { :multipart => true, class: "post-create-form" } do |f| %>
<img id="img_prev" style="margin-bottom:10px;" width=300 height=200 src="#" class="img-thumbnail hidden"/>
<%= f.text_area :body, placeholder: "Share something useful..", class: "form-control post-create-body" %>
<%= f.button "SHARE", class: "btn btn-primary btn-sm btn-create-post", data: {disable_with: "<i class='fa fa-spinner fa-spin'></i> Saving..."} %>
<span class="btn btn-success btn-sm btn-message-file">Upload Image
<%= f.file_field :post_image, class: "choose-message-file", id: "avatar-upload" %>
</span>
<%= f.hidden_field :post_image_cache %>
<% end %>
create.js.erb
$('ul.errors').hide();
$('.alert-danger').hide();
$('.post-index').prepend('<%= j render #post %>');
$('.post-create-body').val('');
$('.btn-create-post').prop('disabled',true);
_post.html.erb
<div class="col-md-2">
<%= link_to user_path(post.user) do %>
<%= image_tag post.user.avatar.url(:base_thumb), class: 'post-avatar' %>
<% end %>
</div>
<div class="col-md-8">
<div class="post-info">
<%= link_to user_path(post.user) do %>
<span class="post-user-name"><%= post.user.full_name %></span>
<% end %>
<span class="post-updated"><%= local_time_ago(post.updated_at) %></span>
</div>
<div class="post-body">
<%= simple_format(find_links(h post.body)) %>
</div>
<div class="post-image" data-postlink="<%= post_path(post) %>">
<% if post.post_image? %>
<button data-toggle="modal" data-target="#post-image-modal">
<%= image_tag post.post_image.url(:base_thumb) %>
</button>
<% end %>
</div>
</div>
UPDATE:
The problem is connected to updating the post object. The update form code can be found in the _post.html.erb, so that's why <%= j render #post %> didn't work. Still don't know what the problem is.
So what works:
1. creating post that has no image
2. updating post that has no image
3. updating post that has image BUT image is not edited
Not working:
1. creating post that has image
2. updating post that has image which is edited
<%= form_for post, method: :patch, remote: true, :html => { :multipart => true } do |f| %>
<div class="modal fade updatepost" id="updatepost_<%= post.id %>" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content" style="text-align:left">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="edittaskmodalohhhhh">Edit Task</h4>
</div>
<div class="modal-body">
<div class="alert alert-danger" style="display:none">
<ul class="errors" style="display:none">
<%= render 'layouts/error_messages', object: f.object %>
</ul>
</div>
<div class="field form-group">
<%= f.file_field :post_image, id: "avatar-upload-update" %>
<%= f.hidden_field :post_image_cache %>
</div>
<div class="field form-group">
<%= f.text_area :body, class: "form-control edit-post-body" %>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" id="updatepostclose">Close</button>
<%= f.button "Update post", class: 'btn btn-primary edit-post-submit', data: {disable_with: "<i class='fa fa-spinner fa-spin'></i> Saving..."} %>
</div>
</div>
</div>
</div>
<% end %>
update.js.erb
$("ul.errors").html("");
<% if #post.errors.any? %>
$('.alert-danger').show();
$('ul.errors').show();
<% #post.errors.full_messages.each do |message| %>
$("ul.errors").append($("<li />").html("<%= message.html_safe %>"));
<% end %>
<% else %>
$('ul.errors').hide();
$('.alert-danger').hide();
$('#updatepost_<%= #post.id %>').modal('hide');
$post = $('<%= j render #post %>');
editPostHideDanger($post);
$('#post_<%= #post.id %>').remove();
$(".new-post-insert").prepend($post);
$("html, body").animate({ scrollTop: 0 }, "slow");
<% end %>
There was some issue (still don't know what) with the bootstrap modals. I changed the structure of the modals and now it's working fine.

Form attribute is not nil but getting First form attribute can't be nil error

I'm getting an error on my edit user modal that says that the first argument can't be nil; however, the form works and pulls the information as expected. The setup is like this:
1) I have a table that summarizes employees
2) each employee has a modify action
3) the modify action opens up a modal with the edit form
The form works and users are able to edit employees. However, every time it's open I get an internal error notification saying that the first argument can't be nil or empty. just to be sure, I'm displaying the employee name in the edit modal to confirm it's not nil (and it's not). The problem is, I'm getting notifications for internal server errors caused by this issue although somehow the form is working.
Any thoughts on what could be causing this and how to fix it?
Employee table code:
<tr>
<td> <%= employee.name %> </td>
<td> <%= employee.status ? t(:active) : t(:inactive) %> </td>
<td> <%= mmm_dd_yy_date(employee.created_at) %> </td>
<td> <%= mmm_dd_yy_date(employee.updated_at) %> </td>
<td> <%= link_to t(:edit), '#', "data-toggle" => "modal", "data-target" => "#EditModal_#{employee.id}", "data-remote" => edit_employee_path(employee) + "#modal-edit-form" %> |
<%= link_to t(:remove), employee, method: :delete, data: { confirm: t(:confirm_remove_employee, name: employee.name)} %>
<!-- Modal -->
<div id='<%= "EditModal_#{employee.id}" %>' class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title"><%= t(:edit_employee) %></h4>
</div>
<div class="modal-body">
<%=render partial: 'edit_form', locals: {employee: employee} %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t(:close) %></button>
</div>
</div>
</div>
</div>
</td>
</tr>
Form modal code:
<div id= "modal-edit-form">
<%= employee.name %>
<%=form_for(employee) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class = "row" >
<div class = "col-xs-6">
<%= f.label :name%>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :status %>
<%= f.collection_select :status, {true: t(:yes), false: t(:no)}, :first, :last, selected: employee.status %>
<%= f.submit t(:update), class: "btn btn-primary"%>
</div>
</div>
<% end %>
</div>
The code looks good to me.
--
The one thing I would say is that including form_for multiple times on the same page is a big no-no - a bunch of conflicts will occur (id etc).
I would personally move the functionality to your employees#edit action as ajax:
#app/controllers/employees_controller.rb
class EmployeesController < ApplicationController
respond_to :js, :html, :json, only: :edit
def edit
#employee = Employee.find params[:id]
respond_with #employee
end
end
#app/views/employees/edit.js.erb
$("<%=j render 'edit' %>").appendTo("body");
// fire modal
#app/views/employees/edit.html.erb
<div id='<%= "EditModal_#{employee.id}" %>' class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title"><%= t(:edit_employee) %></h4>
</div>
<div class="modal-body">
<%=render partial: 'edit_form', locals: {employee: #employee} %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t(:close) %></button>
</div>
</div>
</div>
</div>
#app/views/employees/index.html.erb
<%= link_to t(:edit), '#', data: { toggle: "modal", target: "#EditModal_#{employee.id}", remote: edit_employee_path(employee) + "#modal-edit-form" }, remote: true %>
This way, you'll only be appending the edit forms when you render them.

How to perform a query via bootstrap search box

In the form_tags I can easily add methods and get params from the text_field_tag, for example to query a database or to perform a search.
FORM_TAG
</form>
<%= form_tag usernotes_path, method: 'get' do %>
<%= text_field_tag :query, params[:query], size: 150, placeholder: "Search", class: "searchInput"%>
<%= submit_tag 'Search', class: 'btn btn-success' %>
<% end %>
</div>
Now I am trying to use bootstrap "search" form, but not sure how to achieve the same result as the form_tag (where to put the method, how to add actions, how to perform a query?)
BootStrap Search
<div class="col-sm-3 col-md-3">
<form class="navbar-form" role="search">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search">
<div class="input-group-btn">
<button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
</div>
</div>
</form>
</div>
<div class="col-sm-3 col-md-3">
<%= form_tag usernotes_path, method: 'get', class: 'navbar-form', role: 'search' do %>
<div class="input-group">
<%= text_field_tag :query, params[:query], size: 150, placeholder: "Search", class: "form-control"%>
</div>
<%= submit_tag 'Search', class: 'btn btn-success' %>
<div class="input-group-btn">
<%= button_tag(type: "submit", class: "btn btn-default") do %>
<i class="glyphicon glyphicon-search"></i>
<% end %>
</div>
<% end %>
</div>
This should be it, didn't tested it in an app but I think it will work, let me know in a comment if it's not.

How can I get the modal to display in the following situation?

Firstly, this does not display any errors when I click the link. Can anyone suggest why the modal is not being displayed on the button click?
I do get the contents of the .js.erb file converted to html printed in the Network/Preview section of my dev tools:
$("#contactForm").html("<div class=\"modal fade\" id=\"contactForm\">\n <div class=\"modal-dialog\">\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n ...
I've got the link_to call:
<%= link_to 'Contact', contact_form_path, {:remote => true, 'data_toggle' => "modal", 'data-target' => '#contactForm'} %>
ContactsController method:
def contact_form
#contact = Contact.new
respond_to do |format|
format.js
end
end
routes.rb
get "contacts/contact_form" => 'contacts#contact_form', :as => :contact_form
contact_form.js.erb:
$("#contactForm").html("<%= escape_javascript(render(:partial => 'contacts/contact_form') )%>");
contacts/contact_forml.html.erb
<div class="modal fade" id="contactForm">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">send me a message</h4>
</div>
<div class="modal-body">
<% if flash[:notice] %>
<p class='notice'><%=h flash[:notice] %></p>
<% end %>
<%= form_for(#contact) do |f| %>
<%= f.text_field :name, :placeholder => "first name" %>
<%= f.text_field :email, :placeholder => "email" %>
<%= f.text_area :message, :placeholder => "your message..."%>
<div class="actions">
<%= f.submit :value => "Send Feedback", :class => "btn" %>
</div>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Thanks.
You just forgot to call the modal to show the modal. And modal partial should be rendered into wrapper div, so contact_form.js.erb should look like this:
$("#modal-div").html("<%= escape_javascript(render(:partial => 'contacts/contact_form') )%>");
$("#contactForm").modal();
And the view where you are adding modal should have empty div element
<div id="modal-div"></div>

Resources