0

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?

1 Answer 1

1

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!

Sign up to request clarification or add additional context in comments.

10 Comments

Thank you for the reply. I had gotten pretty far before seeing your answer. I already had a spore_type_counts/create.js.erb file but was struggling to figure out what to put inside it. I had something that was sort of working, but after seeing youre answer I got it perfected. The solution came from adding the following to create.js.erb: $('#spore_count').remove(); $('#samples').show().html("<%= j render('tape_bulk_cocs/sporeCounts') %>");
Is there a way to update the other tabs at the same time, without displaying their contents? Specifically my tab for the Saved Samples. When I submit a spore_type_count I need the sample inside the Saved Samples tab to update so the user can view the spore_count without having to refresh the page
I'm glad I could help! To answer your question about updating other tabs... yes you certainly can. Remember-- you have full access to the currently rendered HTML within your js.erb template so it's just a matter of using jQuery to update the content of the tab(s) that you want. Add another line of JavaScript which selects the other tab and updates its contents to whatever you need.
As a final note, it seems like you are going down the path of making everything dynamically updating "without refreshing the page". I would encourage you to ask yourself why you need to avoid a page refresh, as doing these in-place updates can introduce a lot of complexity and potential spaghetti code if you aren't careful. I would also highly recommend looking into Turbolinks, as it can give you the benefit of seamless page updates via JavaScript without having to code it yourself. Let me know if you have any other questions!
I am only using dynamically updating content for adding something to a sample. Everything else on the site works normally. I was originally using turbolinks, but it was giving me issues with some of my jQuery code, such as my tabs and accordions, causing the functions to only work after visiting the page and refreshing it. I am still new to all this so the simples solution to fix that was to turn off tubolinks for the moment. ( not proper solution i know )
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.