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>
Related
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.
I'm trying to figure out to load a sign UP partial and a sign IN partial in the same bootstrap modal code in an effort to keep it dry.
How is that possible with my current situation?
<%= link_to "Sign in", :sign_in, id: "signin", "data-toggle" => "modal", "data-target" => "#sign-in" %>
modal partial
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<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" id="myModalLabel">Sign In</h4>
</div>
<div class="modal-body">
<%= render "sessions/new" %>
</div>
</div>
</div>
</div>
New session partial
<div class="row">
<div class="span6 offset3">
<%= form_for(:session, url: sessions_path) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit "Sign in", class: "btn btn-large btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
I would render both partials and use javascript to show/hide the correct ones. Make sure in your signup partial you use the class signup in the outermost element and render that within render that right below your signin partial
<%= link_to "Sign in", :sign_in, id: "signin", "data-toggle" => "modal", "data-target" => "#sign-in" %>
<%= link_to "Sign in", :sign_in, id: "signup", "data-toggle" => "modal", "data-target" => "#sign-in" %>
<div class="row signin">
<div class="span6 offset3">
<%= form_for(:session, url: sessions_path) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit "Sign in", class: "btn btn-large btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
Javascript
$(document).ready(function() {
$("#signin").click(function() {
$(".modal .signup").hide();
$(".modal .signin").show();
});
$("#signup").click(function() {
$(".modal .signin").hide();
$(".modal .signup").show();
});
});
Another way
Another way to do it would be to use ajax to load your partial into the body of the modal. You'd want a controller action for it that simply renders a partial and has layout false so you don't get excess layout elements passed with it.
If you don't have a lot, you don't need to make it a new controller, but I just did that here
Javascript
$(document).ready(function() {
$("#signup").click(function() {
setModal("modals/signup");
});
$("#signin").click(function() {
setModal("modals/signin");
});
});
// Doesn't have to be in a function, but it's better to keep it dry.
// Could also add more configuration (like the selector it uses)
function setModal(url) {
$.get(url, function(data) {
$("#myModal .modal-body").html(data);
});
}
Controller
class ModalsController < ApplicationController
def signin
render partial: "sessions/new", layout: false
end
def signup
render partial: "registrations/new", layout: false
end
end
Routes
get "modals/signin", to: "modals#signin"
get "modals/signup", to: "modals#signup"
I've got a page showing details for every #user. Each user has an enrolment, which can has a comment. When I e.g. do this:
<% #user.each do |u| %>
<% the_enrolment = Enrolment.where(user_id: u).first %>
<% end %>
Then in every iteration the enrolment is a different enrolment, as the user changes in every iteration. So far, so simple.
But when I pass this enrolment variable (while looping through) to a partial which contains a form, like this:
<%= render 'the_partial', enrolment: the_enrolment %>
With this form (in the partial view):
<%= form_for enrolment, :url => the_path, remote: true do |f| %>
<%= f.hidden_field :id %>
<%= f.text_area :comment %>
<%= f.submit "Save" %>
Then, in the finally rendered page, every form uses the same enrolment. (They all have the same id and every text_are is pre filled with the content of one of them. What am I doing wrong here?
The complete iteration looks like this:
#user.each do |u|
the_enrolment = Enrolment.where(user_id: u).first
<%= the_enrolment %> # correct id
<%= render 'the_partial', enrolment: the_enrolment %>
end
Thank you very much!
Update
Here is an update with the newest informations. The problem seems to be that the form is placed inside a twitter bootstrap modal. Here is the whole partial:
<%= enrolment.id %> # here it's the correct id
<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Admin Comment</h3>
</div>
<%= form_for enrolment, :url => the_path, remote: true do |f| %>
<div class="modal-body">
<p>
<%= "enrolment in modal: #{enrolment.id}" %> # at this place the id is ALWAYS the id of the very first enrolment
<%= f.hidden_field :id %>
<%= f.text_area :comment_admin %>
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<%= f.submit "Save", class: "btn btn-success", id: "admin-comment-submit-button" %>
</p>
</div>
<% end %>
</div>
If I delete everything on this page concerning the modal, the form works.
I am using rails 4 and I have used jquery text-editor. For omitting html tags, I have used sanitize helper.it's working fine.But edit the form shows html tags in description field.
form.html.erb
<%= simple_form_for #newsletter, html: {class: 'form-inline form-horizontal'}, :validate => true do |f|%>
<br/></br/><br/>
<div class="tabable well">
<div class="tab-content">
<div class="tab-pane active">
<div class="inputs">
<h4 class="" style="border-bottom: 1px solid #dcdcdc;"> <img src="/assets/side_menu/news-and-events.png" alt="Home" ></i> Add NewsLetter</h4><br/><br/>
<div class="offset0">
<%= f.input :name %>
<%= f.input :description, as: 'text', :input_html =>{:rows => '20', :cols => '180', :class => 'wysiwyg input-block-level' }%>
</div>
</div>
<div class="form-actions">
<%= button_tag(type: 'submit', class: "btn btn-primary") do %>
<i class="icon-ok icon-white"></i> Save
<% end %>
<%= link_to new_newsletter_path, class: 'btn btn-inverse' do %><i class='icon-hand-left'> Cancel</i><% end %>
</div>
</div>
</div>
<% end %>
Edit Page
edit.html.erb
<%= render 'news/sidebar'%>
<%= link_to 'Back', newsletters_path, :class => 'btn btn-inverse animated rotateIn' %>
<%= link_to 'View', newsletter_path(#newsletter), :class => 'btn btn-success animated rotateIn pull-right' %>
<br><br>
<div class='row-fluid clear'>
<div class='box gradient'>
<div class=''>
<%= render 'form' %>
</div>
</div>
</div>
I don't know , how to use sanitize in edit page. Please Guide Me..
it appears you are missing a closing </div>
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 %>