曾经多次在项目里用到按某一列给表格Ajax排序的功能,现在从开源项目里redmine里提取出这个sort_helper.rb,稍微修改了下,让它变的更通用:
这里,url_options.merge!("controller" => "#{controller_name}") 是我修改的地方。因为如果controller有命名空间,比如Admin::Users, 那么这里生成的url会是[url]http://www.xxx.com/admin/admin/users.[/url] 显然不是我们想要的,params[:controller_name]为admin/users, 那么我们只需要把这个controller_name用merge方法来让它变成我们想要的。从sort_header_tag方法里传进去就行:
用法:
把sort_helper.rb放到lib目录下,然后,
在controller里:
上面的两种用法,第一个是不支持分页的情况;
第二种是支持分页的情况,不过这个分页是rails自带的分页,如果你用will_paginate,还是一样的用法,把:order_by => sort_clause加到后面就行了。
在view里:
直接使用sort_header_tag方法就行,:controller_name,如果你没有命名空间,则可以不传这个参数,:update是把你需要更新的div的id传回去,因为是ajax排序.
注 :因为我是在rails1.1.6下,所以会有list action, 如果是rails2.0+的版本,使用方法也类似。
module SortHelper
def sort_init(default_key, default_order='asc', name=nil)
@sort_name = name || params[:controller] + params[:action] + '_sort'
@sort_default = {:key => default_key, :order => default_order}
end
def sort_update()
if params[:sort_key]
sort = {:key => params[:sort_key], :order => params[:sort_order]}
elsif session[@sort_name]
sort = session[@sort_name] # Previous sort.
else
sort = @sort_default
end
session[@sort_name] = sort
end
def sort_clause()
session[@sort_name][:key] + ' ' + (session[@sort_name][:order] || 'ASC')
end
def sort_link(column, caption, default_order,controller_name,node)
key, order = session[@sort_name][:key], session[@sort_name][:order]
if key == column
if order.downcase == 'asc'
icon = 'sort_asc.png'
order = 'desc'
else
icon = 'sort_desc.png'
order = 'asc'
end
else
icon = nil
order = default_order
end
caption = titleize(Inflector::humanize(column)) unless caption
sort_options = { :sort_key => column, :sort_order => order }
# don't reuse params if filters are present
url_options = params.has_key?(:set_filter) ?
sort_options :
params.merge(sort_options)
link_to_remote(caption,{:update => node, :url => url_options},
{:href => url_for(url_options.merge!("controller" => "#{controller_name}"))}) +
(icon ? nbsp(2) + image_tag(icon) : '')
end
def sort_header_tag(column, options = {})
caption = options.delete(:caption) || titleize(Inflector::humanize(column))
default_order = options.delete(:default_order) || 'asc'
options[:title]= caption unless options[:title]
content_tag('th',
sort_link(column, caption, default_order,
options[:controller_name],options[:update]),
options)
end
private
# Return n non-breaking spaces.
def nbsp(n)
' ' * n
end
# Return capitalized title.
def titleize(title)
title.split.map {|w| w.capitalize }.join(' ')
end
end
def sort_init(default_key, default_order='asc', name=nil)
@sort_name = name || params[:controller] + params[:action] + '_sort'
@sort_default = {:key => default_key, :order => default_order}
end
def sort_update()
if params[:sort_key]
sort = {:key => params[:sort_key], :order => params[:sort_order]}
elsif session[@sort_name]
sort = session[@sort_name] # Previous sort.
else
sort = @sort_default
end
session[@sort_name] = sort
end
def sort_clause()
session[@sort_name][:key] + ' ' + (session[@sort_name][:order] || 'ASC')
end
def sort_link(column, caption, default_order,controller_name,node)
key, order = session[@sort_name][:key], session[@sort_name][:order]
if key == column
if order.downcase == 'asc'
icon = 'sort_asc.png'
order = 'desc'
else
icon = 'sort_desc.png'
order = 'asc'
end
else
icon = nil
order = default_order
end
caption = titleize(Inflector::humanize(column)) unless caption
sort_options = { :sort_key => column, :sort_order => order }
# don't reuse params if filters are present
url_options = params.has_key?(:set_filter) ?
sort_options :
params.merge(sort_options)
link_to_remote(caption,{:update => node, :url => url_options},
{:href => url_for(url_options.merge!("controller" => "#{controller_name}"))}) +
(icon ? nbsp(2) + image_tag(icon) : '')
end
def sort_header_tag(column, options = {})
caption = options.delete(:caption) || titleize(Inflector::humanize(column))
default_order = options.delete(:default_order) || 'asc'
options[:title]= caption unless options[:title]
content_tag('th',
sort_link(column, caption, default_order,
options[:controller_name],options[:update]),
options)
end
private
# Return n non-breaking spaces.
def nbsp(n)
' ' * n
end
# Return capitalized title.
def titleize(title)
title.split.map {|w| w.capitalize }.join(' ')
end
end
这里,url_options.merge!("controller" => "#{controller_name}") 是我修改的地方。因为如果controller有命名空间,比如Admin::Users, 那么这里生成的url会是[url]http://www.xxx.com/admin/admin/users.[/url] 显然不是我们想要的,params[:controller_name]为admin/users, 那么我们只需要把这个controller_name用merge方法来让它变成我们想要的。从sort_header_tag方法里传进去就行:
用法:
把sort_helper.rb放到lib目录下,然后,
在controller里:
Controller:
helper :sort
include SortHelper
def list
sort_init 'last_name'
sort_update
@items = Contact.find_all nil, sort_clause
end
Controller (using Pagination module):
helper :sort
include SortHelper
def list
sort_init 'last_name'
sort_update
@contact_pages, @items = paginate :contacts,
:order_by => sort_clause,
:per_page => 10
end
helper :sort
include SortHelper
def list
sort_init 'last_name'
sort_update
@items = Contact.find_all nil, sort_clause
end
Controller (using Pagination module):
helper :sort
include SortHelper
def list
sort_init 'last_name'
sort_update
@contact_pages, @items = paginate :contacts,
:order_by => sort_clause,
:per_page => 10
end
上面的两种用法,第一个是不支持分页的情况;
第二种是支持分页的情况,不过这个分页是rails自带的分页,如果你用will_paginate,还是一样的用法,把:order_by => sort_clause加到后面就行了。
在view里:
View (table header in list.rhtml):
<thead>
<tr>
<%= sort_header_tag('id', :title => 'Sort by contact ID',
:controller_name => "users",
:update => "div_id") %>
<%= sort_header_tag('last_name', :caption => 'Name',
:controller_name => "users",
:update => "div_id") %>
<%= sort_header_tag('phone', :controller_name => "users",
:update => "div_id") %>
</tr>
</thead>
<thead>
<tr>
<%= sort_header_tag('id', :title => 'Sort by contact ID',
:controller_name => "users",
:update => "div_id") %>
<%= sort_header_tag('last_name', :caption => 'Name',
:controller_name => "users",
:update => "div_id") %>
<%= sort_header_tag('phone', :controller_name => "users",
:update => "div_id") %>
</tr>
</thead>
直接使用sort_header_tag方法就行,:controller_name,如果你没有命名空间,则可以不传这个参数,:update是把你需要更新的div的id传回去,因为是ajax排序.
注 :因为我是在rails1.1.6下,所以会有list action, 如果是rails2.0+的版本,使用方法也类似。