Updating Pagination When Deleting Items with AJAX In Ruby on Rails

Ruby on Rails & AJAXRuby on Rails

Lately, I seem to be on a tear here with my Ruby on Rails development related posts. I suppose its more for my own documentation, but if it helps someone else out with their own development struggles, even better.

Today, I wanted to find a solution to updating pagination using AJAX. My issue was I use AJAX to update the DOM to remove an item when its deleted. However, the pagination doesn’t update and the listings don’t adjust as you delete them from the middle of the list. My solution, while not rocket science, I think is pretty cool. Basically, just keep using AJAX!

The first thing I need is a div to encapsulate my list. Something like:

     <div id="my_list">
          <%= render :partial => "items", :collection => items %>
          <%= will_paginate items, :renderer => 'ItemLinkRenderer' %>
     </div>

Obviously, that’s my original list inside the my_list div. I’ll get to what ItemLinkRenderer is in a big.

I delete my items from the list by updating the dom from within the delete action. So, something like this:

    @item = Item.find(params[:id])
    if !@item.nil?
        @item.destroy
        render(:update) { |page|
            page.remove dom_id(@item)
        }
    end

This should look pretty straight forward. Delete the item from the database, then remove it from the current document.

But what about updating the pagination and the list? We can remove an item, but how do we adjust the displayed list? Well, just fetch the list of items again.

    @items = Item.paginate :all, :page => params[:page], :per_page => 10
    if @items.length > 0
        page.replace_html "my_items", :partial => "items", :locals => {:items => @items}
    else
        page.replace_html "my_items", "<p>You have no items.</p>"
    end

Ok, so we can render the items. But, if you put this in, then start deleting items, you’ll notice your pagination links get messed up and you have your delete action in the URL. This isn’t good, but, like I mentioned earlier, this is where ItemLinkRenderer comes in. You can define a helper class called ItemLinkRenderer (in item_link_renderer.rb) to render your links properly.

    class ItemLinkRenderer < WillPaginate::LinkRenderer
        def page_link_or_span(page, span_class = 'current', text = nil)
            text ||= page.to_s
            if page and page != current_page
                @template.link_to text, :controller => "items", :action => "list", :page => page
            else
                @template.content_tag :span, text, :class => span_class
            end
        end
    end

This will render your pagination links properly. Hopefully this works out well for anyone who stumbles upon this. Let me know if it does or if you find any errors with what I’ve presented.

Leave a Reply

Your email address will not be published. Required fields are marked *