jqueryruby-on-railsspreeinfinite-scrollkaminari

Rails Spree Kaminari infinite scrolling for the products page


I've tried to use this tutorial Kaminari endless page and also watched Ryan Bates episode #114 Endless Page (revised) and tried to implement an infinite scrolling functionality to my online store.

I don't know for sure how to apply the products rendering in my index.js.erb file because it's quite different implemented in the Spree. I've also forgot to mention that I'm quite new to the Spree platform.

All I've been doing so far was changing these files:

views/spree/products/index.html

<% content_for :sidebar do %>
<div data-hook="homepage_sidebar_navigation">
  <% if "products" == @current_controller && @taxon %>
      <%= render :partial => 'spree/shared/filters' %>
  <% else %>
      <%= render :partial => 'spree/shared/taxonomies' %>
  <% end %>
</div>
<% end %>


<% if params[:keywords] %>
<div data-hook="search_results">
  <% if @products.empty? %>
      <h6 class="search-results-title"><%= t(:no_products_found) %></h6>
  <% else %>
      <%= render :partial => 'spree/shared/products', :locals => { :products => @products, :taxon => @taxon } %>
  <% end %>
</div>

<% else %>
<div id="home-products">
  <div data-hook="homepage_products">
    <%= render :partial => 'spree/shared/products', :locals => { :products => @products, :taxon => @taxon } %>
  </div>
</div>

<% end %>

views/spree/products/index.js.erb

$("#home-products").append('<%= j render(:partial => 'spree/shared/products', :locals => { :products => @products, :taxon => @taxon }) %>');
<% if @products.next %>
   $('.pagination').replaceWith('<%= j paginate(@products) %>');
<% else %>
   $('.pagination').remove();
<% end %>

Here is the partial views/spree/shared/_products.html.erb

<%
  paginated_products = @searcher.retrieve_products if params.key?(:keywords)
  paginated_products ||= products
%>
<% if products.empty? %>
  <%= t(:no_products_found) %>
<% elsif params.key?(:keywords) %>
  <h6 class="search-results-title"><%= t(:search_results, :keywords => h(params[:keywords])) %></h6>
<% end %>

<% if products.any? %>
<ul id="products" class="inline product-listing" data-hook>
  <% reset_cycle('default') %>
  <% products.each do |product| %>
    <% if Spree::Config[:show_zero_stock_products] || product.has_stock? %>
      <li id="product_<%= product.id %>" class="columns three <%= cycle("alpha", "secondary", "", "omega secondary", :name => "classes") %>" data-hook="products_list_item" itemscope itemtype="http://schema.org/Product">
        <div class="product-image">
          <%= link_to small_image(product, :itemprop => "image"), product, :itemprop => 'url' %>
        </div>
        <%= link_to truncate(product.name, :length => 50), product, :class => 'info', :itemprop => "name", :title => product.name %>
        <span class="price selling" itemprop="price"><%= number_to_currency product.price %></span>
      </li>
    <% end %>
  <% end %>
  <% reset_cycle("classes") %>
</ul>
<% end %>

<% if paginated_products.respond_to?(:num_pages) %>
  <%= paginate paginated_products %>
<% end %>

assets/javascripts/store/products.js.coffee

jQuery ->

  if $('.pagination').length
    $(window).scroll ->
       url = $('.pagination .next').attr('href')
       if url && $(window).scrollTop() > $(document).height() - $(window).height() - 50
         $('.pagination').text("Fetching more products...")
         $.getScript(url)
       $(window).scroll()

Here I've changed only the '.next_page' to '.next' according to some comments from the Ryan's episode.

I'm pretty sure the problem is related to the partial, because it's not rendering the products directly, but I don't know how to change this so that it works.

Can anyone help me with this? Thank you.


Solution

  • It looked like I wasn't rendering the right partials
    The content that solved my problem was:

    view/spree/products/index.js.erb

    <%= render 'spree/shared/products.js.erb' %>
    

    I've also created a new js partial for the products because that's where I was actually supposed to make the pagination.

    view/spree/shared/_products.js.erb

    $('ul#products').append('<%= j render(:partial => 'spree/shared/product', :collection => @products) %>');
    
    <% if @products.current_page < @products.total_pages %>
    
    $('.pagination').replaceWith('<%= j paginate @products %>')
    BWLD.can_scroll = true
    
    <% else %>
    
    $('.pagination').remove();
    
    <% end %>