Ajax adding and updating content on a page - ruby-on-rails

Implementing Ajax requests in my rails 3 app has been one of the most frustrating things I've ever done. After days wasted trying to follow people's instructions online, the only thing that seems to work for me is ajax delete.
Users of my site have a profile page, which consists of some info at the top, then they have several different resumes, each of which is contained in a tab on the page. Within each resume are educations, which are what I'd like to be able to add and update dynamically. That is, User has_many resumes, and each resume has_many educations. I render each resume in a div with id equal to it's id. This is the div that I would like to have reload with ajax on form submission. Here's a little code.
user/show:
...
<%= render partial: 'shared/resume' %>
...
shared/resume:
<% if #resumes.any? %>
<div class="tab-content" id="tabResumes">
<%= render partial: 'shared/resume_item', collection: #resumes %>
</div>
<%= will_paginate #resumes %>
<% end %>
shared/resume_item:
<div class="tab-pane" id="<%= resume_item.id %>">
...
# here I render a few different partials which display the different elements of the resume, such as educations.
# I'd like to reload this area on form submission.
...
</div>
educations_controller:
def create
#resume = Resume.find(params[:resume_id])
#education = #resume.educations.build(params[:education])
respond_to do |format|
if #education.save
format.html { redirect_to(#student, :notice => 'Education created.') }
format.js
else
format.html {render :action => "new" }
format.js
end
end
end
views/educations/create.js.erb
$('#<%=#resume.id%>').html("<%= escape_javascript()%>"); //not sure what to call here, nothing I've tried has given me any success.
I'd also like to make updating refresh the same div, but I wanted to get create working first. Anybody have any advice for how to make this work? The ajax submit appears to be going through, as I am getting
Rendered educations/create.js.erb
Completed 200 OK in 52ms
in the console.

Try having your create.js.erb along the lines of:
$('#<%= #resume.id %>').replaceWith("<%= escape_javascript render(:file => 'shared/resume_item.html.erb') %>");
Alternatively you can also use the jquery .appendTo method instead of replaceWith, but, in this case I think replaceWith works better.

Related

Form submit renders ajax partial showing code in text with Paperclip attachment

The files upload fine, and the form submission goes through with a Paperclip attachment, but the partial it's supposed to render through ajax shows up as text on a new page, instead of rendering the modal partial. Otherwise, without a Paperclip attachment, the form goes through normally as well, but the partial also renders normally. This is what shows up on the page, the code as text:
$("#actionEdit").html("Thank you, application received :) \n\n<br><br>\n\nYou will receive an Update regarding your application within one business day.\n");
And it shows up at http://localhost:3000/support_tickets.js which is wrong, should be just localhost. The pictures upload though, and the form submits normally. If there is no attachment, the page renders normally.
the form:
<div class="form-group">
<%= f.input :house_insurance_image, hint: "Upload a picture of your house insurance if you plan on holding an event at your house." %>
</div>
controller:
def create
#support_ticket = current_fan.support_tickets.build(support_ticket_params)
authorize #support_ticket, :create?
#fan = Fan.find(#support_ticket.fan_id)
respond_to do |format|
format.js
end
end
create.js
...
<% elsif #support_ticket.save %>
$("#actionEdit").html("<%= j render 'success' %>");
<% end %>
Issue was I was uploading in a modal, which requires gem remotipart.

How to replace a div tag in my view using Ajax

I want to replace a div tag on my Images index page using Ajax. Right now, I have the following:
_sub.html.erb
<% #group.images.each do |image| %>
<%= image_tag image.pic.url(:medium) %>
<%= button_to '+1', image_upvote_path(image), remote: true, method: :post %>
<% end %>
index.html.erb
<div id="next_group">
<%= render 'sub' %>
</div>
upvote.js.erb
$("#next_group").empty();
$("#next_group").append("<%= j render 'sub' %>");
In my images_controller
def index
#group = Group.offset(rand(Group.count)).first
end
def upvote
#image = Image.find(params[:image_id])
#image.votes.create
respond_to do |format|
format.html { redirect_to groups_path }
format.js
end
end
And in my routes, I have
image_upvote POST /images/:image_id/upvote(.:format) images#upvote
My understanding of what is going on:
On my index page I have a div container that renders the sub partial that I want users to see. Inside the sub partial, I have a button_to helper that has the remote: true attribute(?) included as well as the path/action that clicking that button will initiate. The action is the images#upvote. So in the images controller, I define what I want to happen when the button is clicked (an upvote is created), but I also say that I want it to respond with Ajax, which happens because I've declared remote: true.
Here's where I start getting a little confused. Since Ajax is being used, does rails automatically look for the upvote.js.erb file since it's the upvote action that is occurring?
My problem right now is that the vote is being created just fine, but I don't think the javascript in upvote.js.erb is being executed. The page will stay on the current #group that is being displayed, without rendering a new _sub partial. So I guess I'm not sure if there is a problem with the javascript, or maybe something with the way I have the controller, views, and routes set up.
maybe button not belongs to any form, try using link_to or add remote options to the path

Whats the most efficient way to update a partial after an AJAX form submit in Rails 3

I have a page with code as follows:
<div>
<%= render 'form' %>
</div>
<div id="item_container">
<%= render #item %>
</div>
where form is a form for "#item" and "render #item" renders a partial that represents "#item". The form uses remote: :true and submits using AJAX.
Whats the simplest and most efficient way in rails 3 to update the entire #item partial when the form is submitted.
In your controller action you need to add a respond_to block
respond_to do |format|
format.html
format.js
end
and you can write a view where you directly write javascript code in it (given your action name is 'update')
update.js.erb
$('#item_container').html('<%= j render(#item) %>');
Note the 'j' that escape for JS response

Kaminari index from both data-remote and html messing with links

I have an index view for a model(nested ) that never gets called from the model, but is rendered from a couple different models. One view can render the index with either JS or html. With JS is it in a #related div in the show view and a data-remote link. Another option uses the same controller action to render it only has html.
All was fine until I added Kaminari paging. In the full page view, there was no #related div so paging didn't work. I broke out the guts into a partial and added a #related div and rendered the partial. From js I just rendered the partial from JS. That worked fine in the full page view, but in the show page it would render the partial, but the links didn't work, looks like it renders the entire show page. Clinking on another tab and then going back to the Progressions tab loads the partial and all works fine. It is just on the initial load of the show page that I can't get the page links to work.
I can load another tab that does not use paging first and solve my problem, but this was kind of the main information that you go to this page for.
Any ideas?
EDIT Request for code
The controller action method. The index method in this controller also sets #progressions
def progressions
authorize! :read, Progression
#stage = Stage.find(params[:id])
#progressions = #stage.progressions_by_score.page(params[:page]).per(20)
if params[:status] && !params[:status].blank? && #progressions
#progressions = #progressions.where(status: params[:status]).page(params[:page]).per(20)
end
respond_to do |format|
format.js
format.html {render :template => "progressions/index"}
end
end
The progressions.js.erb file in the stages view
$("#related").html("<%= escape_javascript(render('progressions/index'))%>");
The relations div in the show view. This is pretty much my scaffold template where I display or link to related information. The <div id="related"> is where any date-remote links will load the data. On initial load it loads the _index partial.
<div class="relations">
<span class="navspan">
<%= link_to 'Progressions: Status ->', progressions_stage_path(#stage), :'data-remote' => true,
:onclick => '$("#progression_status").val("")' %>
<span class="huh">
<%= hidden_field_tag :stage_id, params[:id]%>
<%= select_tag :progression_status, options_for_select(Progression.statuses["all"], params[:status]),
:prompt => 'All', :class => 'f-left' %>
</span>
<%= link_to 'Assessors', assessors_stage_path(#stage), :'data-remote' => true %>
<%= link_to 'Events', events_stage_path(#stage), :'data-remote' => true %>
<%= link_to 'Select', select_stage_path(#stage) if can? :select_candidates, #stage %>
<%= link_to 'Ad Mgmt', edit_ad_stage_path(#stage) if can? :manage_ad, #stage %>
</span>
<div class="f-clear"></div>
<div id="related">
<%= render "progressions/index"%>
</div>
</div>
The index.html.haml file
#related
= render "progressions/index"
The _index.html.haml file is just an index table listing the progressions but it does contain:
= paginate #progressions, :remote => true
Shortly after posting some code, I went back in my memory and used javascript to load the related div. I've tried to stay away from javascript, but in this case I added this to the end of the page after adding :id => "status_id" to the progressions link:
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$("#status_link").trigger("click");
})
</script>
While this fixes my problem, I still don't understand why the initial html response does not respond to the page links in the related div. I'll leave that as something else to learn. I'll put it in coffescript after I figure out how to have fire only on initial load of the show page.

Render specific model id?

I'm looking to take an example of a model (in this case, Book), and render a specific instance of that model by ID.
The model is just a basic scaffold generated model - usual show method;
def show
#book = Book.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #book }
end
end
I'm looking to embed an instance of this inside of the view:
<div class="tab-pane active" id="tab1">
<%= render :template "books/show", :book => 1 %>
</div>
There's something I'm doing wrong here, I can tell. But I don't know where to proceed from here! Any help is really appreciated. I know I need to somehow pass the book ID, but I can't figure out how to do that. Thanks!
<%= render :template "books/show", :book => 1 %> only renders the partial, it doesn't load the page.
What you need to do is call the route "books/show/#{book_id}" from an iframe for example.
Maybe?
<div class="tab-pane active" id="tab1">
<%= render 'books/show', book: #book %>
</div>
The variable #book, you create in your controller is automatically made visible into the template. So, if your template show.html.erb is placed in the right place, then
<%= #book.title %>
should render the text (I assume the Book has an attribute title here).
I am not sure where the html you present is located. It does not make sense in show.html.erb, since you actually reference that file from there. If you would like to render a link to a book, then you should do
<%= link_to 'Link text', book_path(1) %>

Resources