-
Notifications
You must be signed in to change notification settings - Fork 76
Customizing Table View
The most basic form of the will_filter_table_tag is:
<%= will_filter_table_tag(@users) %>
This will generate a table with all available columns of the User object:
But we don’t really care for the created_at and updated_at values, and we want to display only a select few columns. We also want to use a specific order of columns, so that birthday comes before sex. You can do this like that:
<%= will_filter_table_tag(@users, :columns => [:id, :first_name, :last_name, :birthday, :sex]) %>
Now you have restricted the columns to the selected few:
But what if we want instead of showing first name and last name, combine them both into a single column called name? Here is how we would do this:
<%= will_filter_table_tag(@users, :columns => [ :id, [:name, lambda{|obj| "#{obj.first_name} #{obj.last_name}"}], :birthday, :sex ]) %>
Defining a column as an array is good for quick key, value mapping. But when you want to do some fun stuff with the table, a better way would be to use hashes with named attributes. So the above example can do written like this:
<%= will_filter_table_tag(@users, :columns => [ :id, {:key => :name, :value => lambda{ |obj| "#{obj.first_name} #{obj.last_name}" }}, :birthday, :sex ]) %>
And both of the above examples will result in:
Alright, so far so good. What if we were like Facebook, and decided that referring to gender as sex was not such a good idea. So we decide to use Gender instead of Sex as the column name. You can do this like that:
<%= will_filter_table_tag(@users, :columns => [ :id, {:key => :name, :value => lambda{ |obj| "#{obj.first_name} #{obj.last_name}" }}, :birthday, {:key => :sex, :title => 'Gender'} ]) %>
Here is what it would look like now:
There is still one issue in this table, the combined name column is no longer sortable. Since it is not really a column of the model, the table is not sure what to sort on. We can fix it like this:
Let’s say we want this column to still be sortable on the last name. We can simply do it like the following:
<%= will_filter_table_tag(@users, :columns => [ :id, {:key => :last_name, :value => lambda{|obj| "#{obj.first_name} #{obj.last_name}"}, :title => 'Name'},
:birthday, {:key => :sex, :title => ‘Gender’}
]) %>
Here is the result:
Almost good, but not good enough. We made the name column sortable on the last name model field. But user is not clearly seeing what the column is sorted on. So let’s add some code to correct that:
<%= will_filter_table_tag(@users, :columns => [ :id, { :key => :last_name, :value => lambda{|obj| if @users.wf_filter.column_sorted?(:last_name) raw("<span style='font-weight:normal'>#{obj.first_name} <strong>#{obj.last_name}</strong></span>") else "#{obj.first_name} #{obj.last_name}" end }, :title => 'Name' }, :birthday, { :key => :sex, :title => 'Gender' } ]) %>
Here is the result:
Now things start to get interesting. What if we want the name column to be sortable on the First Name or the Last Name based on the user preference. Here is how you would do this:
<%= will_filter_table_tag(@users, :columns => [ :id, {:key => :name, :value => lambda{ |obj| if @users.wf_filter.column_sorted?(:last_name) raw("<span style='font-weight:normal'>#{h(obj.first_name)} <strong>#{h(obj.last_name)}</strong></span>") elsif @users.wf_filter.column_sorted?(:first_name) raw("<span style='font-weight:normal'><strong>#{h(obj.first_name)}</strong> #{h(obj.last_name)}</span>") else "#{obj.first_name} #{obj.last_name}" end }, :title => lambda{ |filter| if filter.column_sorted?(:last_name) first_name_link = link_to("First Name", filter.to_params(:wf_order => :first_name, :wf_order_type => 'asc'), :title => "sort by first name ascending") last_name_link = link_to("Last Name", filter.to_params(:wf_order => :last_name, :wf_order_type => (filter.order_type == 'asc' ? 'desc' : 'asc')), :title => "sort by last name #{(filter.order_type == 'asc' ? 'descending' : 'ascending')}", :style=>'color:black;font-weight:bold') elsif filter.column_sorted?(:first_name) last_name_link = link_to("Last Name", filter.to_params(:wf_order => :last_name, :wf_order_type => 'asc'), :title => "sort by last name ascending") first_name_link = link_to("First Name", filter.to_params(:wf_order => :first_name, :wf_order_type => (filter.order_type == 'asc' ? 'desc' : 'asc')), :title => "sort by first name #{(filter.order_type == 'asc' ? 'descending' : 'ascending')}", :style=>'color:black;font-weight:bold') else last_name_link = link_to("Last Name", filter.to_params(:wf_order => :last_name, :wf_order_type => 'asc'), :title => "sort by last name ascending") first_name_link = link_to("First Name", filter.to_params(:wf_order => :first_name, :wf_order_type => 'asc'), :title => "sort by first name ascending") end [first_name_link, last_name_link].join(' / ').html_safe }, :sortable => true, :sort_key => lambda{ |filter| filter.column_sorted?(:first_name) ? :first_name : :last_name} }, :birthday, { :key => :sex, :title => 'Gender' } ]) %>
And here is what you get: