“Load More” button using Ajax and jQuery and page pagination in Ruby on Rails

I myself am only new to the study of RoR, but when developing my own project, there was a desire instead of classical pagination using the will_paginate gem to make it more convenient using javascript. This should be a classic button, when clicked, the following n-records are loaded. I did not find a solution to the problem in Russian, there is in English, but I found only cumbersome and inconvenient options. As the saying goes, if you want to do something well, do it yourself. Here's what happened.

We will paginate using the same will_paginate gem, we will also use it if the user has javascript disabled.

So first install the gem:

gem 'will_paginate'

bundle install

Then we start with the controller. In my case, this will be a pagination of the user list. Accordingly, this is an 'index' action, which should respond to a javascript (: js) request:

respond_to :html, :xml, :json, :js
 def index
    @users = User.paginate(page: session[:page])
    respond_with @users

Session Hash
used as a counter. A little later we will return to him.

Next, go to the index.html.erb view and add the pagination:

All users

    <%= render @users %>
<%= will_paginate @users %>
<% if @users.next_page %>
<%= button_to 'More users', {action: "index", new_req: true }, method: :get, remote: true, class: "btn btn-primary btn-large" %>
<% end %>

I will explain a few points. Here we have two blocks. The first c id “without_button” adds a standard page break gem line. We will use it when javascript is disabled: The


second block includes a button. It will be shown only if the number of users is enough to break into records. The default for will_paginate is 30 entries. Accordingly, if there are 30 or fewer, the next_page method will return nil and the block will not be loaded. If javascript is disabled, there should be no button. Accordingly, we prescribe in css:

#load_more_users {
  display: none;

The button transfers control to our action with the hash params [: new_req] , the value of which we set to true. The explanation will be further.

So now we need to understand that we need to download the following entries. Moreover, the counter should be equal to 1 (first page) when loading or updating the page. Here params [: new_req] helps us , until the button is pressed it is nil, if true, then increase the counter by 1. Another point, if javascript is disabled, pagination will occur through the params [: page] hash . So we will assign its value to the counter. Hope accessible explained. So we create the following method:

 def up_page 
   session[:page] = case 
                   when params[:new_req] then session[:page]+1
                   when params[:page] then params[:page]
                   else 1

Initially, I used a class variable as a counter, since it is not re-created as an instance variable when I call the action again. But the companion below correctly noted that the class variable will be common to all users. So I replaced it with a session hash.

The method must be executed before the index action:

 before_action :up_page, only: :index

Now the fun part. We pass to CoffeeScript. Add the following code to the app / assets / javascripts / users.js.coffee file

      $('#load_more_users form').after('')
      $('#load_more_users').click ->

The first line hides the classic pagination, the second shows the button. Then, after our button, we add a second clone button with a darkened background, which will be shown instead of the first button when you click on it. In principle, the clone button is optional. Instead, you can show the download bar or any other picture / gif.

It remains to connect Ajax. Add the following code to index.js.erb:

$('.users').append('<%= j render @users %>').siblings('#load_more_users').find("button").hide().siblings('form').show();
<% unless @users.next_page %>
<% end %>

After loading the following user n-records, we hide the clone button and again show our form with the first button. We create the clone button in order to prevent the button from being pressed again until the records are loaded. Well, delete our button when all records from our ActiveRecord :: Relation array are already shown.

That's all. I hope this information will be useful to someone.

UPD .:@@page Replaced the class variable with session [: page]

Also popular now: