Wednesday, September 3, 2014

Ajax and partials

As I keep adding more jQuery options to Rails my app (renamed Speechy), I discover the need to pass parameters via Ajax requests. In the app, one of the pages has two tabs: a click on one of the tabs shows a list of emotions to be selected, and a click on the second tab shows the images selected accordingly. Data from the first click is supposed to be passed via Ajax click event, and the first tab is supposed to display selected images without reloading the entire page.

This is done as follows:

In show.html.erb I set up the tabs to be called. emotion-tabs renders contents_form partial with checkboxes for emotions. In test-tabs, blank_response partial will be replaced with selected images with the help of jQuery.

<div id="student-tabs">
    <ul>
        <li><a href="#test-tabs" class='test-tabs-button'>Test</a></li>
        <li> <a href ='#emotion-tabs'> Select emotions</a></li>
    </ul>

    <div id="test-tabs">
         <%= render 'blank_response' %>
    </div>

    <div id="emotion-tabs">
        <%= render 'contents_form' %>
    </div>
</div>

_contents_form partial with a remote:true link:

<h3> Selecting emotions </h3>
    <% tag_selection Content.select_tags(current_user.id) do |tag| %>
        <li>
            <%= check_box_tag "tag_ids[]", tag.id, false, class: 'submittable' %>
            <%= tag.tagname %>
        </li>
    <% end %>
    <br/>
    <%= link_to "Select", show_selected_path(@student),
          remote: true, class: "btn btn-primary btn-xs submitme" %>

show_selected_path(@student) is a custom route that belongs to a method in a controller (in my case Student controller). The method gets the passed params[:tag_ids]:

def show_selected
    @selected_contents = Content.joins(:tags).
        where(tags: { id: params[:tag_ids]}).belongs_to_user(current_user.id)
    respond_to do |format|
         format.js
    end
end

The submitme button collects data from selected checkboxes as an array of ids and passes it to the show_selected method in controller:

$('.submitme').on('click',function(){
    var tag_array = $('input:checked').valList().split(',');
    var pathname = window.location.pathname;
    $.ajax({
         type: "GET",
         url: pathname+'/show_selected',
         data: { tag_ids: tag_array },
         success: function()
         {
            // alert('Success occurred');
         },
         error: function(){
            alert('Error occurred');
         }
    });
    return false;
 }); 

Finally, the show_selected method takes a responds_to format.js block. Since format.js does not take any arguments, this means that the file to be called has the same name as the method:

show_selected.js.erb:

<% if @selected_contents.count <= 0 %>
    $("#test-tabs").html("<%= escape_javascript(render 'blank_response') %>");
<% else %>
    $("#test-tabs").html("<%= escape_javascript(render 'shared/selected_contents') %>");
<% end %>


No comments :

Post a Comment