Make flatpickr input required
Asked Answered
F

8

11

I'm using the amazing flatpickr on a project and need the calendar date to be mandatory.

I'm trying to have all the validation in native HTML, so I was naively trying with just adding the required attribute to the input tag, but that doesn't appear to be working.

Is there a way of natively making a date mandatory with flatpickr or do I need to write some custom checks?

Ferreira answered 19/7, 2017 at 11:51 Comment(0)
R
14

You can easily achieve this by:

Passing allowInput:true in flatpickr config.

As example:

flatpickrConfig = {
    allowInput: true, // prevent "readonly" prop
};

From the documentation:

Allows the user to enter a date directly into the input field. By default, direct entry is disabled.

The downside of this solution is that you should enable the direct entry (but ideally form validation should occur whether or not direct entry is enabled).

But if you don't want to enable the direct entry to solve this problem, you can use the code below as a workaround:

flatpickrConfig = {
    allowInput:true,
    onOpen: function(selectedDates, dateStr, instance) {
        $(instance.altInput).prop('readonly', true);
    },
    onClose: function(selectedDates, dateStr, instance) {
        $(instance.altInput).prop('readonly', false);
        $(instance.altInput).blur();
    }
};

This code remove the readonly property when it is not in focus so that html validation can occur and add back the readonly prop when it is in focus to prevent manual input. More details about it here.

Recidivism answered 20/10, 2021 at 12:40 Comment(1)
this is the best answer overall.Pumpernickel
H
3

This is what I came up with to make as complete of a solution as possible. It prevents form submission (when no date selected and input is required), ensures browser native "field required" message pops up and prevents the user typing in the value directly.

flatpickrConfig = {
    allowInput: true, // prevent "readonly" prop
    onReady: function(selectedDates, dateStr, instance) {
        let el = instance.element;
        function preventInput(event) {
            event.preventDefault();
            return false;
        };
        el.onkeypress = el.onkeydown = el.onkeyup = preventInput; // disable key events
        el.onpaste = preventInput; // disable pasting using mouse context menu

        el.style.caretColor = 'transparent'; // hide blinking cursor
        el.style.cursor = 'pointer'; // override cursor hover type text
        el.style.color = '#585858'; // prevent text color change on focus
        el.style.backgroundColor = '#f7f7f7'; // prevent bg color change on focus
    },
};

There is one disadvantage to this: Keyboard shortcuts are disabled when the flatpickr is open (when the input has focus). This includes F5, Ctrl + r, Ctrl + v, etc. but excludes Ctrl + w in Chromium 88 on Linux for some reason. I developed this using a rather old flatpickr version 3.1.5, but I think it should work on more recent ones too.

In case you want to use altFormat (display one date format to user, send other date format to server), which also implies setting altInput: true, you have to also change the onReady function to use instance.altInput instead of instance.element.

The onReady event listener can probably be attached to the instance after initializing it. However, my intention of using flatpickr with vue-flatpickr-component where you cannot elegantly access the individual flatpickr instances, made me use the config field instead.

I haven't tested it on mobile devices.

Hosanna answered 2/9, 2021 at 8:5 Comment(1)
dunno why but when i test its not work, and there is no any error or other information.Uncommitted
F
2

After digging a bit into the GitHub repo, I found a closed issue that points out that the issue will not be addressed.

In the same Issue page there is a workaround that seems to do the trick:

$('.flatpickr-input:visible').on('focus', function () {
    $(this).blur()
})
$('.flatpickr-input:visible').prop('readonly', false)
Ferreira answered 19/7, 2017 at 16:5 Comment(0)
A
2

copy attr name from prior input type hidden to rendered flatpickr input just do this

$('[name=date_open]').next('input').attr("name","date_open");
$('[name=date_close]').next('input').attr("name","date_close");
Acrocarpous answered 27/10, 2018 at 17:17 Comment(0)
Y
1

Have been working on this for a couple of days now, finally getting the result I was after.

NOTE: I am using flatpickr with jQuery validation

As you would know flatpickr uses an alternative field for the date input, the actual field where the date is stored is hidden, and this is the key.

jQuery validation has a set of defaults, and by default hidden fields are not subject to validation, which normally makes perfect sense. So we just have to turn on the validation of hidden fields to make this work.

    $.validator.setDefaults({
        ignore: []
    });

So my validator rules are then fairly normal:

    var valid = {
                rules: { dateyearlevel: {required: true} },
                messages: { dateyearlevel: {required: "The date is required"} }
    };
    $("#myform").validate(valid);

That should allow you to ensure the date is required. In my situation I wanted my date to only be required is a checkbox was checked. To do this we changed the rule above:

    var valid = {
                rules: { dateyearlevel: {
                  required: function() { return $("#mycheckbox").is(":checked") } 
                } },
                messages: { dateyearlevel: {required: "The date is required"} }
    };
    $("#myform").validate(valid);
Ytterbium answered 23/5, 2019 at 0:54 Comment(0)
H
0

In case this helps someone, I'm using parsley.js for frontend validation and it works good with flatpickr

enter image description here

Hypothermia answered 26/2, 2020 at 15:22 Comment(0)
O
0

Just to expand a bit more on this, I found the ignore value set as an empty array did the trick for me also. You can just add this to your validate call back. Also displaying was a bit of an issue so I updated the errorPlacement to allow for flatpickr inputs like so.

$('#my-form').validate({
    errorPlacement: function (error, element) {
        if (element.hasClass('js-flatpickr') && element.next('.js-flatpickr').length) {
            error.insertAfter(element.next('.js-flatpickr'));
        } else if (element.parent('.input-group').length) {
            error.insertAfter(element.parent());
        } else {
           error.insertAfter(element);
        }
    },
    ignore: [],
    rules: {
        'startdate': { required: true }
    },
    messages: {
        'startdate': {required: "Start Date is required"}
    },
    submitHandler: function(form) {
        // ajax form post
    }
});
Oregon answered 26/3, 2021 at 13:21 Comment(0)
U
0

in my case vue ( dunno why ) , i would like to comment for comment by @mik13ST

fyi: the default allowInput i think is true, no need to define, i didnt set the properties and my flat-pickr also work on testing.

i use

// this work in flat-pickr || #code_01
<small class="text-danger">
 {{ validationContext.errors[0] }}
</small>

instead of

// work for all element except <flat-pickr #code_02 , dunno why not work
<b-form-invalid-feedback>
 {{ validationContext.errors[0] }}
</b-form-invalid-feedback>

full code

<validation-provider
                  #default="validationContext"
                  name="Waktu Selesai Berkegiatan *"
                  vid="Waktu Selesai Berkegiatan *"
                  rules="required"
                >
<flat-pickr
                      id="Waktu Selesai Berkegiatan *"
                      v-model="item.pip_time_end_rl"
                      placeholder="Waktu Selesai Berkegiatan *"
                      class="form-control"
                      static="true"
                      :config="dpconfig" 
                      :state="getValidationState(validationContext)"
                    />
// put here the message of error ( required ) #code_01 instead of #code_02
</validation-provider>

if younot use composite, just use

#default="{ errors }" // in validation provider
:state="errors.length > 0 ? false : null" // in element for example flat-pickr
{{ errors[0] }} // to print out the message
Uncommitted answered 24/11, 2022 at 1:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.