jbox-web / ajax-datatables-rails

A wrapper around DataTable's ajax methods that allow synchronization with server-side pagination in a Rails app
MIT License
587 stars 228 forks source link

Argument out of range error with date_range cond #398

Closed clveranis closed 2 years ago

clveranis commented 3 years ago

I recently implemented a date_range filter using YADCF and while the date range filter itself works fine, I receive the following error if I try to use the native search input:

Completed 500 Internal Server Error in 7ms (ActiveRecord: 1.7ms)
ArgumentError (argument out of range):

I have them implemented like such:

View_columns:

def view_columns
    @view_columns ||= {
      ...
      submitted_on: { source: "Order.created_at", cond: :date_range,  delimiter: '-yadcf_delim-',
      ...
    }
end

YADCF JS Initialization:

yadcf.init(tableElement.DataTable(), [{
  column_number : 11, 
  filter_type: "range_date", 
  datepicker_type: 'bootstrap-datetimepicker', 
  date_format: 'YYYY-MM-DD', 
  filter_container_id: 'yadcfDateDiv'
}]);

I don't mind setting the date column to be searchable: false to disable the search feature (which removes the error) but then the date range filter stops working. Any ideas would be greatly appreciated, thanks!

clveranis commented 2 years ago

So my work around for this was adding 2 initializers to my rails app:

class Time def self.parsable?(string) begin parse(string) true rescue ArgumentError false end end end

config/initializers/ajax_datatables_rails.rb

module AjaxDatatablesRails module Datatable class Column module Search def non_regex_search case cond when Proc filter when :eq, :not_eq, :lt, :gt, :lteq, :gteq, :in searchable_integer? ? raw_search(cond) : empty_search when :start_with text_search("#{formatted_value}%") when :end_with text_search("%#{formatted_value}") when :like text_search("%#{formatted_value}%") when :string_eq raw_search(:eq) when :string_in raw_search(:in) when :null_value null_value_search when :date_range

        if Time.parsable?(formatted_value)
          date_range_search
        else
          text_search("%#{formatted_value}%")
        end

      end
    end
  end
end

end end

----

The idea is to check if the searched string is a valid datetime format and can be parsed into a valid `Time` object, if it's not, then the search function treats the column as if its searching it as a regular string (i.e. if `cond: :datetime` was not explicitly set). This way you can search against that column as either a string or date time.

One additional thing I noticed is that if you are using the `bootstrap-datetimepicker` option with `YADCF` and you clear the date inputs manually (without using the red 'X' button that `YADCF` creates), then it will submit the search string `-yadcf_delim-` to the filter search, thus causing your table to search for a date value matching that delim string. My workaround for that was:

In some .js file where you have yadcf.init()

var dateRanges = $('#yadcf-filter--orders-datatable-from-date-11,#yadcf-filter--orders-datatable-to-date-11'); dateRanges.each(function() { $(this).on('dp.hide', function(e){ if (dateRanges[0].value.length === 0 && dateRanges[1].value.length === 0) { yadcf.doFilter('clear', '-orders-datatable', 11, 'range_date'); } }); });



I'm aware this is a bit 'hacky' and I'm sure there is probably a more elegant way to do all of the above but this is where I landed and my table is functioning as desired. Maybe this will help some future Googler or if anyone has any feedback on a better way to do this then I'm all ears. Happy coding!