How To: Create Infinite Scrolling with jQuery

Yuki Nishijima edited this page Nov 1, 2017 · 17 revisions

This wiki page is no longer maintained and kept here only as a record as jQuery is no longer part of Rails and there are many other good resources for implementing infinite scroll on the web today. Please also do not use the examples below in production.

Introduction

This tutorial is designed to get you up and running with a basic Rails application with endless scrolling for blog posts. We will use Kaminari for pagination, and Infinite Scroll (no longer maintained) for the JavaScript functionality.

You can find the full source code for this demonstration at github.com/zzak/endless-kaminari-demo.

Please note that we will also be using Rails 4, in case that makes a difference It may affect how your controller looks when it is generated.

For an alternate implementation using the simpler jquery-infinite-pages plugin, check the plugin's README.

Tutorial

Start by creating a new rails application.

$ rails new endless_kaminari

Don't forget to change into your new application's directory before continuing with this tutorial.

$ cd endless_kaminari

Dependencies

Add 'kaminari' to your Gemfile and run the bundle command.

$ echo "gem 'kaminari'" >> Gemfile
$ bundle

Run the jQuery generator to download the necessary files and setup your Rails app to use jQuery.

$ rails generate jquery:install

Last thing we will need is the Infinite Scroll plugin.

$ curl -k -o vendor/assets/javascripts/jquery.infinitescroll.js https://raw.githubusercontent.com/paulirish/infinite-scroll/master/jquery.infinitescroll.js

We can quickly add this to our application like so:

$ echo "//= require jquery.infinitescroll" >> app/assets/javascripts/application.js

Creating Posts

Let's create a model, which will be used to showcase the infinite scrolling and migrate the database.

$ rails generate scaffold Post title:string author:string body:text
$ rake db:migrate

In order to populate our database with some dummy data, we will use the SecureRandom module from Ruby's standard library. Add the following code to your db/seeds.rb file:

require 'securerandom'

75.times do
  Post.create(
    :title => "My Post #{SecureRandom.hex(2)}",
    :author => SecureRandom.hex(6),
    :body => SecureRandom.hex(32)
  )
end

Then run rake db:seed to complete this step.

Controller

In this step we're just going to change the index action of our PostsController to use Kaminari. It should end up looking like this:

# app/controllers/posts_controller.rb

# ...

# GET /posts
# GET /posts.json
def index
  @posts = Post.order(:created_at).page(params[:page])
end

# ... more actions

Views

Now that we have Kaminari set up in our controller, we need to add the pagination to the index view:

$ echo '<%= paginate @posts %>' >> app/views/posts/index.html.erb

We're also going to add a few classes that we will need for the JavaScript, and extract the @posts view to a partial (app/views/posts/_post.html.erb).

Your index view should end up looking like this, please note the id="posts" on the table and class="page" on the tbody:

# app/views/posts/index.html.erb

<h1>Listing posts</h1>

<table id="posts">
  <thead>
    <tr>
      <th>Title</th>
      <th>Author</th>
      <th>Body</th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>

  <tbody class="page">
    <%= render @posts %>
  </tbody>
</table>

<br>

<%= link_to 'New Post', new_post_path %>
<%= paginate @posts %>

The extracted partial should end up looking like this:

# app/views/posts/_post.html.erb
<tr class="post">
  <td><%= post.title %></td>
  <td><%= post.author %></td>
  <td><%= post.body %></td>
  <td><%= link_to 'Show', post %></td>
  <td><%= link_to 'Edit', edit_post_path(post) %></td>
  <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>

Note the class="post" on the table-row, this will be important for our JavaScript later.

The last view that we will need is the index view for our JavaScript request to append the new results. Given our current scaffolding views in the previous examples, it should look something like this:

# app/views/posts/index.js.erb
$("#posts").append("<tbody class='page'><%= escape_javascript(render(@posts)) %></tbody>");

Note we are using the same tbody tag as the index.html.erb view.

JavaScript

Now it's time to tie it all together with some simple JavaScript. Add the following to your posts.js.coffee:

# app/assets/javascripts/posts.js.coffee

$(document).ready ->
  $("#posts .page").infinitescroll
    navSelector: "nav.pagination" # selector for the paged navigation (it will be hidden)
    nextSelector: "nav.pagination a[rel=next]" # selector for the NEXT link (to page 2)
    itemSelector: "#posts tr.post" # selector for all items you'll retrieve

# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

Note we are using CoffeeScript in this example.

We should now have a working application featuring infinite scrolling and kaminari. If you have any issues with this code, or kaminari, please report them to the issue tracker.