Cody Pritchard
Cody Pritchard

Reputation: 695

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?

Upvotes: 0

Views: 780

Answers (1)

Carlos Ramirez III
Carlos Ramirez III

Reputation: 7434

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!

Upvotes: 1

Related Questions