View API
Use the Filterrific ActionView API to:
- Display the list of matching records and the form to update filter settings.
- Update the filter settings via AJAX form submission.
- Reset the filter settings.
Filterrific works best with AJAX updates. The library comes with form observers for jQuery and an AJAX spinner. See below for a code example without AJAX.
View example 1
View example 2
View example 3
View code walk through
index.html
This is the main template for the students list. It is rendered on first load and includes:
- The Filterrific filter form.
- The
_list.html.erb
partial for the actual list of students. When we refresh the list, we just update the_list.html.erb
partial via AJAX.
You can use any type of form inputs for the filter. For multiple selects we have had great success with Harvest’s Chosen multi select input widget.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<%# app/views/students/index.html.erb %>
<h1>Students</h1>
<%#
Filterrific adds the `form_for_filterrific` view helper:
* adds dom id 'filterrific_filter'
* applies javascript behaviors:
* AJAX form submission on change
* AJAX spinner while AJAX request is being processed
* sets form_for options like :url, :method and input name prefix
%>
<%= form_for_filterrific @filterrific do |f| %>
<div>
Search
<%# give the search field the 'filterrific-periodically-observed' class for live updates %>
<%= f.text_field(
:search_query,
class: 'filterrific-periodically-observed'
) %>
</div>
<div>
Country
<%= f.select(
:with_country_id,
@filterrific.select_options[:with_country_id],
{ include_blank: '- Any -' }
) %>
</div>
<div>
Registered after
<%= f.text_field(:with_created_at_gte, class: 'js-datepicker') %>
</div>
<div>
Sorted by
<%= f.select(:sorted_by, @filterrific.select_options[:sorted_by]) %>
</div>
<div>
<%= link_to(
'Reset filters',
reset_filterrific_url,
) %>
</div>
<%# add an automated spinner to your form when the list is refreshed %>
<%= render_filterrific_spinner %>
<% end %>
<%= render(
partial: 'students/list',
locals: { students: @students }
) %>
_list.html
The _list.html.erb
partial renders the actual list of students. We extract it
into a partial so that we can update it via AJAX response.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<%# app/views/students/_list.html.erb %>
<div id="filterrific_results">
<div>
<%= page_entries_info students # provided by will_paginate %>
</div>
<table>
<tr>
<th>Name</th>
<th>Email</th>
<th>Country</th>
<th>Registered at</th>
</tr>
<% students.each do |student| %>
<tr>
<td><%= link_to(student.full_name, student_path(student)) %></td>
<td><%= student.email %></td>
<td><%= student.country_name %></td>
<td><%= student.decorated_created_at %></td>
</tr>
<% end %>
</table>
</div>
<%= will_paginate students # provided by will_paginate %>
index.js
This javascript template updates the students list after the filter settings were changed.
1
2
3
4
5
<%# app/views/students/index.js.erb %>
<% js = escape_javascript(
render(partial: 'students/list', locals: { students: @students })
) %>
$("#filterrific_results").html("<%= js %>");
application.js
If you use jQuery and the asset pipeline, then just add this line to your application.js file to get the form observers and the spinner:
1
//= require filterrific/filterrific-jquery
Disable AJAX auto form submits
By default Filterrific will automatically submit the filter form as soon as you change any of the filter settings. Sometimes you may not want this behavior, e.g., if the rendering of the filtered records is fairly expensive.
The auto submit behavior is triggered by the filter form’s id which is automatically added by the form_for_filterrific
helper method. In order to deactivate AJAX auto submits, just override the DOM id for the form with something other than the default of filterrific_filter
. If you still want to submit the form via AJAX (just not automatically on every change), also add the remote: true
option to form_for_filterrific
. Otherwise the form will be submitted as regular POST request and the entire page will reload.
Then you must add a regular submit button, and make sure you don’t add the .filterrific-periodically-observed
class to any inputs. Now Filterrific will update the list only when you manually submit the form:
1
2
3
4
<%= form_for_filterrific @filterrific, html: { id: 'filterrific-no-ajax-auto-submit' } do |f| %>
...
<%= f.submit 'Filter' %>
<% end %>
Sort by Column Title
Filterrific provides sortable column header links which toggle sort direction
with the filterrific_sorting_link()
method.
filterrific_sorting_link
The filterrific_sorting_link(@filterrific, ...)
method provides toggle
sorting of attributes defined in a sorted_by
scope.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<%# app/views/students/_list.html.erb %>
<div id="filterrific_results">
<div>
<%= page_entries_info students # provided by will_paginate %>
</div>
<table>
<tr>
<th><%= filterrific_sorting_link(@filterrific, :name) %></th>
<th><%= filterrific_sorting_link(@filterrific, :email) %></th>
<th><%= filterrific_sorting_link(@filterrific, :country) %></th>
<th><%= filterrific_sorting_link(@filterrific, :registered_at) %></th>
</tr>
<% students.each do |student| %>
<tr>
<td><%= link_to(student.full_name, student_path(student)) %></td>
<td><%= student.email %></td>
<td><%= student.country_name %></td>
<td><%= student.decorated_created_at %></td>
</tr>
<% end %>
</table>
</div>
<%= will_paginate students # provided by will_paginate %>
filterrific_sorting_link()
must be placed in the view partial.
sorted_by
The filterrific_sorting_link()
method is expecting asorted_by
scope which
contains the column headers and the model attribute to sort by. Column headers
are automatically capitalized.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
scope :sorted_by, ->(sort_option) {
direction = /desc$/.match?(sort_option) ? "desc" : "asc"
case sort_option.to_s
when /^name/
order("LOWER(students.name) #{direction}")
when /^email/
order("LOWER(students.email) #{direction}")
when /^country/
order("LOWER(students.country) #{direction}")
when /^registered_at/
order("LOWER(students.decorated_created_at) #{direction}")
else
raise(ArgumentError, "Invalid sort option: #{sort_option.inspect}")
end
}