Reputation: 339
I have used jquery-datatables-rails to present some information for my index and have added in filters following this. However the datatable appears to be ignoring the filters and they are not shown as part of the requested json in the get request.
I've enclosed my index method, the datatables class, my index view and the coffeescript I'm running.
Index Method
def index
@sbcons = Subcontractor.scoped
if filters = params[:filter]
@sbcons = @sbcons.where(sbcon_type: filters[:type]) unless filters[:type].blank?
@sbcons = @sbcons.where(cscs_card: filters[:cscs]) unless filters[:cscs].blank?
@sbcons = @sbcons.where(approved_status: filters[:approved]) unless filters[:approved].blank?
end
respond_to do |format|
format.html
format.json do
render json: SubcontractorsDatatable.new(view_context, @sbcons)
end
end
end
Index View
<% provide(:title, 'All Subcontractors') %>
<h1>Subcontractors List</h1>
<div class="filter">
<%= form_tag(method: :get, id: "filter_form") do %>
<%= label_tag :sbcon_type, "Type" %>
<%= select_tag "filter[type]", options_for_select([[],["Labour Only"], ["Specialist"], ["Both"]]) %>
<%= label_tag :cscs_card, "CSCS" %>
<%= select_tag "filter[cscs]", options_for_select([[],["Yes"], ["No"]]) %>
<%= label_tag :approved_status, "Approved Status" %>
<%= select_tag "filter[approved]", options_for_select([[],["Approved"], ["Not Approved"]]) %> <br>
<%= link_to "Filter", '#', id: "filterbutton", class: "btn btn-mini" %>
<% end %>
<br>
</div>
<table id="subcontractors" class="table table-condensed table-hover display" data-source="<%= subcontractors_url(format: "json") %>">
<thead>
<tr>
<th>Name</th>
<th>Contact Number</th>
<th>CSCS</th>
<th>Type</th>
<th>Scotland</th>
<th>NE England</th>
<th>NW England</th>
<th>Midlands</th>
<th>SE England</th>
<th>SW England</th>
<th>London</th>
<th>Wales</th>
<th>Operatives</th>
<th>Product Liability</th>
<th>Employer Liability</th>
<th>Public Liability</th>
<th>Contractors All Risk</th>
<th>Status</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<%= javascript_tag do %>
$('#filterbutton').click(function (){
$('#subcontractors').dataTable().fnDraw();
});
<% end %>
Datatables class
class SubcontractorsDatatable
delegate :params, :h, :link_to, to: :@view
def initialize(view, sbcons)
@view = view
@sbcons = sbcons
end
def as_json(option = {})
{
sEcho: params[:sEcho].to_i,
iTotalRecords: Subcontractor.count,
iTotalDisplayRecords: subcontractors.total_entries,
aaData: data
}
end
private
def data
subcontractors.map do |subcontractor|
[
link_to(subcontractor.sbcon_name, subcontractor),
h(subcontractor.con_tel_num),
h(subcontractor.cscs_card),
h(subcontractor.sbcon_type),
h(subcontractor.scot),
h(subcontractor.ne_eng),
h(subcontractor.nw_eng),
h(subcontractor.mid),
h(subcontractor.se_eng),
h(subcontractor.sw_eng),
h(subcontractor.ldn),
h(subcontractor.wales),
h(subcontractor.op_avail),
h(subcontractor.ins_prod),
h(subcontractor.ins_emp),
h(subcontractor.ins_pub),
h(subcontractor.ins_con_all),
h(subcontractor.approved_status)
]
end
end
def subcontractors
@subcontractors ||= fetch_subcontractors
end
def fetch_subcontractors
subcontractors = Subcontractor.order("#{sort_column} #{sort_direction}")
subcontractors = subcontractors.page(page).per_page(per_page)
if params[:sSearch].present?
subcontractors = subcontractors.where("sbcon_name like :search or con_tel_num like :search", search: "%#{params[:sSearch]}%")
end
subcontractors
end
def page
params[:iDisplayStart].to_i/per_page + 1
end
def per_page
params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10
end
def sort_column
columns = %w[sbcon_name con_tel_num cscs_card sbcon_type scot ne_eng nw_eng mid se_eng sw_eng lon wales op_avail ins_prod ins_emp ins_pub ins_con_all approved_status]
columns[params[:iSortCol_0].to_i]
end
def sort_direction
params[:sSortDir_0] == "desc" ? "desc" : "asc"
end
end
Coffeescript
jQuery ->
$('#subcontractors').dataTable
sPaginationType: "bootstrap"
sdom: "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>"
bProcessing: true
bServerSide: true
sAjaxSource: $('#subcontractors').data('source')
fnServerParams: (aoData) ->
for form_element in $('#filter_form').serializeArray()
aoData.push
name: form_element.name
value: form_element.value
Upvotes: 1
Views: 461
Reputation: 339
At Abram's suggesting I looked through if filters part and found that it was never being called. I fixed this by amending the form_tag as follows:
<%= form_tag('#', method: :get, id: "filter_form") do %>
From here I found that the filters were being passed but ignored. Abram suggested moving the logic to the fetch_subcontractors method in the datatables class and changed the initalize method at the same time to reflect this
def initialize(view, subcontractors)
@view = view
end
def fetch_subcontractors
subcontractors = Subcontractor.order("#{sort_column} #{sort_direction}")
subcontractors = subcontractors.page(page).per_page(per_page)
if params[:sSearch].present?
subcontractors = subcontractors.where("sbcon_name like :search or con_tel_num like :search", search: "%#{params[:sSearch]}%")
end
if filters = params[:filter]
binding.pry
subcontractors = subcontractors.where(sbcon_type: filters[:type]) unless filters[:type].blank?
subcontractors = subcontractors.where(cscs_card: filters[:cscs]) unless filters[:cscs].blank?
subcontractors = subcontractors.where(approved: filters[:approved]) unless filters[:approved].blank?
end
subcontractors
end
with these corrections the filters work properly and display the correct results.
Upvotes: 1