Nic Lin's Blog

喜歡在地上滾的工程師

讓分頁用無限捲軸載入

Infinite Scrolling to load more records from database using Ruby on Rails

Gems installed

gem 'will_paginate', '~> 3.1'

gem 'bootstrap-sass', '~> 3.3', '>= 3.3.6'

gem 'bootstrap-will_paginate', '~> 0.0.10'

Gem removed

gem 'turbolinks'

建立 Post Controller

運用場景:

Post#index 的 view ,可以無限下拉來達到 Load more

controller 要能 respond JS

class PostsController < ApplicationController
  def index
    @posts = Post.paginate(page: params[:page],
                           per_page: 5).order('created_at DESC')

    respond_to do |format|
      format.html
      format.js
    end
  end
end
$( document ).ready(function() {

  //infinite scrolling
  if ($('.loading-next-page').size() > 0) {
    $(window).on('scroll', function() {
      more_posts_url = $('.loading-next-page').attr('href');
      if (more_posts_url && ($(window).scrollTop() > $(document).height() - $(window).height() - 60)) {
        $('.loading-next-page').replaceWith('<p class="loading-next-page">Load more...</p>');
        $.getScript(more_posts_url);
      }
    });
  };
});

先做一個 Ajax helper

  def render_ajax_next_page_link(posts)
    link_to("next page", posts_path(page: posts.next_page), remote: true, class: 'btn btn-primary loading-next-page hidden' )
  end

class 裡面的 hidden 可加可不加,不加的話在 Load more 會有一瞬間跑出來這個按鈕就是了

<div id="listing-infinite-scrolling">
    <%= render @posts %>
</div>

<div>
    <%= render_ajax_next_page_link(@posts) %>
</div>

記得把 partial 補上

<h2><% post.title %></h2>
<p><% post.description %></p>

這邊 tag 跟樣式可以自訂,本文章不多贅述

寫 js.erb

$('#listing-infinite-scrolling').append('<%= j render @posts %>');

<% if @posts.next_page %>
  $('.loading-next-page').replaceWith('<%= j render_ajax_next_page_link(@posts) %>');
<% else %>
  $(window).off('scroll');
  $('.loading-next-page').remove();
<% end %>

接下來應該可以在 post#index 頁面,做到無限捲軸下拉載入了

如果要做成用按鈕載入新的樣式,只要把 JS 行為拔掉,改用 render_ajax_next_page_link 這個 helper 出來的 button 就可以了(記得把 class 裡面的 hidden 移除掉,否則你會看不到這個按鈕)

Done.

參考來源

3 ways to load more records from database using Ruby on Rails

comments powered by Disqus