Rambling Labs Blog Ramblings on software development

  • Rails 3.1 - will_paginate and AJAX

    For a project that I'm currently working on, I have a couple of list views that needed pagination. So I went with the ol' will_paginate gem (which I first saw years ago when I didn't even consider myself a developer) to take care of this.

    It's as simple as including a line with gem 'will_paginate' on your Gemfile, running bundle install, and include this in the controller:

    class OrdersController < ApplicationController
      def index
        @orders = Order.paginate(page: params[:page], per_page: 10)
      end
    end
    

    And this in the view orders/index.html.erb:

    <div id="orders">
      <ul>
        <% @orders.each do |order| %>
          <li>
              <!-- Show order stuff -->
          </li>
        <% end %>
      </ul>
      <%= will_paginate @orders %>
    </div>
    

    Now, this last line will generate your pagination links. Then, a problem arose. There was one specific view which I didn't want to be refreshed completely when clicking the pagination links.

    Partials, jQuery and AJAX to the rescue

    I found a post (in a blog with a really familiar name), which described a way to do it that just seemed magical. But that combined with a stack overflow question that I found, seems to be the way to go. Here is what I did:

    In the controller:

    class OrdersController < ApplicationController
      def index
        @orders = Order.paginate(page: params[:page], per_page: 10)
      end
    end
    

    Encapsulate the order list in the partial view orders/_orders.html.erb:

    <ul>
      <% @orders.each do |order| %>
        <li>
            <!-- Show order stuff -->
        </li>
      <% end %>
    </ul>
    <%= will_paginate @orders %>
    

    The resulting index view orders/index.html.erb:

    <div id="orders">
      <%= render partial: 'orders' %>
    </div>
    

    The view orders/index.js.erb:

    $('#orders').html('<%= render partial: 'orders' %>');
    $.setAjaxPagination();
    

    The JavaScript (CoffeeScript) file assets/orders.js.coffee:

    $ ->
      $.setAjaxPagination = ->
        $('.pagination a').click (event) ->
          event.preventDefault()
          loading = $ '<div id="loading" style="display: none;"><span><img src="/assets/loading.gif" alt="cargando..."/></span></div>'
          $('.other_images').prepend loading
          loading.fadeIn()
          $.ajax type: 'GET', url: $(@).attr('href'), dataType: 'script', success: (-> loading.fadeOut -> loading.remove())
          false
    
      $.setAjaxPagination()
    

    And that's it!
    Fairly easy I would say!

  • blog comments powered by Disqus