Backbone: How to implement pagination

Reading Time: 4 minutes

Step by step Pagination using Kaminari, Rails, Coffeescript, Backbone and Underscore

In this tutorial I'm going to show you how to implement pagination using Kaminari, Ruby on Rails, Coffeescript, Backbone js, Underscore js and Eco templates. I created a screencast to help you in the process. But you can also follow the post and do it on your own.

For those of you who like screencasts:

Important links(resources):

How to implement uploads in backbone:
Here's the base repository to start this tutorial:
The final code (using pagination):
You can see the working demo in the following url:
So, let’s start by cloning the repo. To do this we need to run code from console:
 $ git clone
Now let’s go into the project directory
$ cd jqueryfileuploadbackbone
$ bundle install
The next step: adding the Kaminari Gem

Now we are going to open our Gemfile

and add this
 gem 'kaminari
And now, we need to run bundle install again.
$ bundle install
The first file that we are going to edit is the router file called "qr codes router"
The next code that we need to add is used to define the two main routes in our backbone:
class Jqueryfileuploadbackbone.Routers.Qrcodes extends Backbone.Router
      ''              : 'showManageImages'
      'qrcodes/:page' : 'showManageImages'
      'qrcode/add'    :   'addNewImage'
And now we need to declare our function to show the manage images view.
The most important thing to explain here is the page number. By default we are using "page 1", if the user does not specify another page number (page = 1)
 showManageImages: (page = 1) ->
     $('#container-app').html JST['helpers/loading']
      #now it’s time to declare the model
      # After the line we are declaring our model and
      model = new Jqueryfileuploadbackbone.Models.Qrcode()
      # and the view
      # to show all the images we need to specify in “el” element the div 
      # which is used to attach that view and when we do the fetch data the view 
      # is prepared to show all elements in the DOM and the data.
      indexView = new Jqueryfileuploadbackbone.Views.QrcodesIndexView 
                                                model: model
                                                el: $('#container-app')

       indexView.model.fetch data: { page: page }

Now add the loading template:

First we need to create the directory helpers, and create the loading file


And the content is just a div with a loading image

  #cargando{style: 'width: 150px; margin-left: auto; margin-right: auto' }
    = image_tag 'loading.gif'

If we look at the content of the template, we can see that we are using an image, and for that reason you need to add an image to app/assets/images path If you want to see a loading image before rendering the images list.

Next step: create QrcodesIndex view and its template

Let's create the file in

And this is the content:

 class Jqueryfileuploadbackbone.Views.QrcodesIndexView extend Backbone.View

   # in the initialize method we add the next code
   # because we need to specify that we want to render the template when the model changes its data
   initialize: ->
      @model.on "change", @render, @

   helpers: ->
      blockPagination: ->
         segment = @model.get('perPage')
         current =  @model.get('current_page') || 1
         range = _.range (current - segment), (current + segment+1), 1
         middle = _.filter range, (num) =>
         num > 0 and num <= @model.get('total_pages')

      nextPage: ->
         value = @model.get('current_page')
         total_pages = @model.get('total_pages')
         value = value + 1 unless value is total_pages

      previousPage: ->
         value = @model.get('current_page')
         value = value - 1 unless value is 1

      currentPage: ->

      totalPages: ->

  template: JST['qrcodes/index']

  render: ->
     # we need to merge the main view with the helpers function if we want to be able to use it  in the template with those functions.
    @$el.html @template _.extend(@, @helpers)
    @addOnebyOne @model.get('models')

    # In the addOnebyOne function we use a function from Underscore js called _.each 
    # to iterate through the models and append each model in a 
    # new view called QrcodesShow.

 addOnebyOne: (models) ->
    _.each models, ((qrcode) ->
       view = new Jqueryfileuploadbackbone.Views.QrcodesShowView model: qrcode
       @$('#qrcodes').append view.render().el
    ), @
Additionally, I want to talk about the helper’s section:

If you need any additional function, just add it in the helpers sections.

First, to create the Qrcodesshow view, we are going to create the template for QrcodesIndexView:

with this content:

  <%- JST['helpers/pagination'](@) %>
  = link_to 'Add new Image', '#qrcode/add'
  <%- JST['helpers/pagination'](@) %>

If we look at the content, we are using an additional template called "pagination" with this content:


In this template, we are just using our functions declared in helpers section in QrcodesIndexView

%a{ href: '#qrcodes/<%= @previousPage() %>', id: 'page-prev' ,class: "no-underline <%= 'disabled' if @currentPage() is 1 %>" } Prev
<% for page in @blockPagination(): %>
%a{ href: '#qrcodes/<%= page %>', id: 'page-<%= page %>', class: "<%= 'active' if page is @currentPage() %>", data: { page: '<%= page %>' }  } <%= page %>
<% end %>
%a{ href: '#qrcodes/<%= @nextPage() %>', id: 'page-next', class: "no-underline <%= 'disabled' if @currentPage() is @totalPages() %>", data: { page: '<%= @currentPage() %>' }  } Next

To hide the "previous" or "next" button when there are not many images, we can use this simple CSS code, in my case located in:


with the content:

  .disabled{display: none;}
So, let’s continue with the QrcodesShow located in :
The content
 class Jqueryfileuploadbackbone.Views.QrcodesShowView extends Backbone.View

    # we specify the template for the view
    template: JST['qrcodes/show']

    # and the render method to show the image
    render: ->
       @$el.html @template qrcode: @model
and the file:
the content of the template:
 %a{href: '#', alt: "<%= @image_file_name %>"}
    %img{ alt: "<%= %>", width: "200", src: "/system/qrcodes/<%= @qrcode.image_file_name %>"}

The remaining part of this tutorial we are going to do all the necessary backend's code.

Now we need to create an additional controller in my case it is:
 class MainController < ApplicationController
     def index ; end
And rename:
Now let’s open the file:

and we need to add this content to use Kaminari:

  class QrcodesController < ApplicationController

    def index
        qrcodes_paginated = Qrcode.order('id').page(params[:page]).per(PER_PAGE_RECORDS)

       respond_to do |format|
          format.json { render :json => {:models => qrcodes_paginated, :current_page => params[:page].to_i, :perPage => PER_PAGE_RECORDS, :total_pages => qrcodes_paginated.num_pages } }

And we need to configure our routes:

the content:
 get "qrcodes/create"

 scope "api" do
    resources :qrcodes, format: false 

 root :to => 'main#index'

Now if we run our web server from console:

 $ rails s

We can see this... and yaaay! it works!

Important links(resources):

How to implement uploads in backbone:
The base repository to start this tutorial:
The final code(using pagination):
You can see working the demo in the following url:

I hope you enjoyed this post! Let me know if the video helped you. See you later!

 Heriberto Perez Magaña
  Software Engineer at

You May Also Like