At peopleforce.io we try to stick to as close as possible to the recommended Rails technologies available. This includes Stimulus JS to help separate common behaviours into their own controllers across views.
For our data pickers we decided to use flatpickr which we found to be the most flexible datepicker available in terms of configuration options and features.
Below is our implementation of how we extracted Flatpickr to be used across all our Rails forms with support of different date formats and I18n.
.erb
<%= f.date_picker_field :date_of_birth %>
application_form_builder.rb
class ApplicationFormBuilder < ActionView::Helpers::FormBuilder
def date_picker_field(method, options = {})
options[:class] = options[:class] || "form-control "
options[:placeholder] = Current.user.settings.date_format
options[:data] = {"target" => "date-picker.picker"}
options[:autocomplete] = "off"
options[:required] = options[:required] if options[:required]
inner_tags = @template.text_field_tag(method, (options.has_key?(:value) ? options[:value] : object.send(method)), options)
inner_tags << @template.hidden_field(@object_name, method, {
value: (options.has_key?(:value) ? options[:value] : object.send(method).try(:strftime, "%F")),
data: {target: "date-picker.input"}
})
return @template.content_tag(:div, inner_tags, {data: {controller: "date-picker"}})
end
end
date_picker_controller.js
// LOCALE - global variable for preferred user language. eg. "en", "es", "ru"
// DATE_FORMAT - global variable for user preferred date format. eg. 'DD-MM-YYYY'
import {Controller} from "stimulus"
import flatpickr from "flatpickr";
import "flatpickr/dist/l10n/ru.js"
import "flatpickr/dist/l10n/uk.js"
import moment from "moment";
flatpickr.l10ns.en.firstDayOfWeek = 1;
export default class extends Controller {
static targets = ["input", "picker"]
initialize() {
let controller = this;
var DATE_FORMATS = {
"YYYY-MM-DD": "Y-m-d",
"DD.MM.YYYY": "d.m.Y",
"DD/MM/YYYY": "d/m/Y",
"MM.DD.YYYY": "m.d.Y",
"MM/DD/YYYY": "m/d/Y"
}
let flatPicker = flatpickr(this.pickerTarget, {
"dateFormat": DATE_FORMATS[DATE_FORMAT],
"locale": LOCALE,
allowInput: true,
onClose: (selectedDates, dateStr, instance) => {
if (dateStr == "") {
controller.inputTarget.value = "";
instance.clear();
} else {
let d = instance.parseDate(controller.pickerTarget.value, DATE_FORMATS[DATE_FORMAT]);
flatPicker.setDate(d);
controller.inputTarget.value = moment(d).format("YYYY-MM-DD");
controller.pickerTarget.value = instance.formatDate(d, DATE_FORMATS[DATE_FORMAT]);
}
}
});
}
}
Top comments (0)