Topic: Ajax, will_paginate, sort, search
I'm trying to get search, sort, will_paginate and ajax working
together. I've seen lots of will_paginate and ajax, but not with
search and sort.
I've got the search and sort part working ok, but the will_paginate
brings back the entire page from the ajax call, and also i can't seem
to get the data back from will_paginate properly (i.e. the page number
changes, but the data items do not change properly - e.g. if there are
5 items with 3 per page, and we move to page 2, then the first two
items from page 1 remain and the third is delete, but it moves to page
2 in the pagination). I also have problems passing the sort and search
criteria with the will_paginate ajax call)
view code index.html.erb
<label for="item_name">Filter on item name : </label>
<%= text_field_tag("search", params['search'], :size => 10 ) %><img alt="spinner" id="spinner" src="/images/ajax-loader.gif"
style="display:none" />
<%= observe_field "search", :update => "", # :frequency => 0.5,
:with => "search", :url => { :controller => "companies", :action =>
"search" },
:loading => "Element.show('spinner')",
:complete => "Element.hide('spinner')" %>
<div id="container">
<%= render :partial => 'contents' %>
</div>
view code _contents.html.erb
<table>
<thead>
<tr><td <%= sort _td_class_helper "reg_number" %>>
<%= sort_link_helper "Reg Number", "reg_number" %>
</td>
<td <%= sort_td_class_helper "name" %>>
<%= sort_link_helper "Name", "company_name" %>
</td>
<td <%= sort_td_class_helper "city" %>>
<%= sort_link_helper "City", "city" %>
</td>
<td <%= sort_td_class_helper "country" %>>
<%= sort_link_helper "Country", "country" %>
</td></tr>
</thead>
<tbody>
<% if @companies.size == 0 %><p>No Companies found...</p>
<% else %>
<% @companies.each do |company| %>
<tr class="<%= cycle("even","odd") %>">
<td><%=h company.company_registered_number %></td>
<td><%= link_to company.company_name, :action => "show", :id =>
company.id %></td>
<td><%=h company.city %></td>
<td><%=h company.country.country %></td></tr>
<% end %>
</tbody>
</table>
<p><%= will_paginate(@companies, :renderer =>
"RemoteLinkRenderer",:remote => { :update => '', :action =>
'search', :params => { 'search' => params[:search], 'sort' =>
params[:sort] }})%>
</p><% end %>
model
def self.search(search, page, sortby)
sort = case sortby
when "company_name" then "companies.company_name"
when "reg_number" then
"companies.company_registered_number"
when "city" then "companies.city"
when "country" then "countries.country"
when "company_name_reverse" then "companies.company_name
DESC"
when "reg_number_reverse" then
"companies.company_registered_number DESC"
when "city_reverse" then "companies.city DESC"
when "country_reverse" then "countries.country DESC"
endpaginate(:per_page => 3, :page => page, :include =>
'country',
:conditions => ['company_name like ? and companies.id !=
0', "%#{search}%" ], :order => sort)
end
Controller
def search
@companies = Company.search(params[:search], params[:page],
params[:sort])
:order => 'company_registered_number ASC')
respond_to do |format|
format.js{
render :update do |page|
page['container'].replace_html :partial => "contents"
end
}
end
end
application_helper
def sort_td_class_helper(param)
result = 'class="sortup"' if params[:sort] == param
result = 'class="sortdown"' if params[:sort] == param + "_reverse"
return result
end
def sort_link_helper(text, param)
key = param
key += "_reverse" if params[:sort] == param
options = {
:url => { :params => params.merge({:action => 'search',:sort =>
key, :page => nil})},:update => '',
:before => "Element.show('spinner')",
:success => "Element.hide('spinner')"
}
html_options = {
:title => "Sort by this field",
:href => url_for(:params => params.merge({:action =>
'search',:sort => key, :page => nil}))}
logger.info " options #{options} html_options #{html_options}"
link_to_remote(text, options, html_options)
end
# app/helpers/remote_link_renderer.rb
class RemoteLinkRenderer < WillPaginate::LinkRenderer
def prepare(collection, options, template)
@remote = options.delete(:remote) || {}
super
endprotected
def page_link(page, text, attributes = {})
@template.link_to_remote(text, {:url => url_for(page), :method
=> :get}.merge(@remote))
end
end