Cody Pritchard Cody Pritchard - 1 month ago 6
Ajax Question

Rails 4 - Rendering partial with AJAX/JS

I need to add some AJAX/JS functionality to my rails application.

This is the page I'm working on:
enter image description here

To display the content of the tab above, I'm calling

<%= render 'tape_bulk_cocs/sporeCounts' %>


Inside this partial is the following code (minus the html tags to display text):

<div id="samples">
<% if @tape_bulk_coc.tape_bulk_coc_samples.any? %>
<% @tape_bulk_coc.tape_bulk_coc_samples.each do |cur| %>
<% if !cur.spore_type_count %>
<%= link_to 'Add Spore Count', new_spore_type_count_path(:tape_bulk_coc_sample_id=>cur.id), :remote=>true, :id => "new_spore_count", class: "tiny button expanded" %>
<% end %>
<% end %>
<% end %>
</div>


Inside my
spore_type_counts_controller/new
I have:

def new
@spore_type_count = SporeTypeCount.new
@tape_bulk_sample_id = params[:tape_bulk_coc_sample_id]
@category_count = [["Rare: 1 to 10","Rare: 1 to 10"], ["Low: 11 to 100","Low: 11 to 100"], ["Medium: 101 to 1000","Medium: 101 to 1000"], ["High: > 1000","High: > 1000"]]

respond_to do |format|
format.js
end
end


Then, in
app/views/spore_type_counts/new.js.erb


$('#samples').hide().after( '<%= j render("spore_type_counts/form") %>' );


So far everything works as intended, and when I click "Add Spore Count" the tab changes to appear like so:
enter image description here

This is where the problem I'm having happens.

When I submit the
spore_type_counts/form
I go into the
create
action for the controller which is this:

def create
@spore_type_count = SporeTypeCount.new(spore_type_count_params)

respond_to do |format|
if @spore_type_count.save
format.js { render 'tape_bulk_cocs/sporeCounts'}
end
end
end


Once here, everything submits to the database correctly, but the page does not change. I cannot figure out how to re-render the
tape_bulk_cocs/sporeCounts
partial (first picture).

Essentially, once I submit the form, I need to get from the
spore_type_count_controller/new
back to the
tape_bulk_coc_controller/show
and update my objects, without refreshing the page.

How can I do this? Or do I need to restructure my application to work differently?

Answer

You need to update the DOM using the content from the partial, much like you did in the new.js.erb template. Right now you are just saying "render this partial" but the page does not know how to update itself with that content unless you tell it how to via JavaScript.

Try creating a spore_type_counts/create.js.erb file which will be executed after the SporeTypeCounts#create action is run. Inside that template, add the JavaScript code which will update your page using the content that you render from the partial.

For example,

// hide the previous content
$("#spore-count-form").remove();

// show the new content
$('#samples').html("<%= j render('tape_bulk_cocs/sporeCounts') %>");

A few things to note:

  • Update the selectors above to fit your app. I usually use data-attributes to mark something that I'm going to manipulate using JavaScript (e.g. data-ujs-target=spore-form). That way the JS interactions don't get broken by someone accidentally changing an ID or CSS class.

  • You may have to update your markup in order to modify it using jQuery.

  • If tape_bulk_cocs/sporeCounts uses any instance variables, make sure they are defined within the the SporeTypeCounts#create action otherwise the partial won't render. (NOTE: you really should avoid using instance variables within partials for this reason)

Hope that helps!

Comments