RyanMacG
RyanMacG

Reputation: 339

Filters being ignored in jquery-datatables-rails

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

Answers (1)

RyanMacG
RyanMacG

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

Related Questions