DEV Community

Cover image for Rails Stimulus Flatpickr Controller

Rails Stimulus Flatpickr Controller

Andrew Cetinic
Founder of
・2 min read

At 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.


   <%= f.date_picker_field :date_of_birth %>


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"}})


// 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 = "";
                } else {
                    let d = instance.parseDate(controller.pickerTarget.value, DATE_FORMATS[DATE_FORMAT]);
                    controller.inputTarget.value = moment(d).format("YYYY-MM-DD");
                    controller.pickerTarget.value = instance.formatDate(d, DATE_FORMATS[DATE_FORMAT]);

Discussion (0)

Forem Open with the Forem app