Adding a datepicker field on the checkout

Quite often - it's necessary to capture a date from the customer on the checkout. This could be to allow the customer to specify a preferred delivery date - but there are a number of other uses you might have.

There are a plenty of different javascript date pickers available online. We're going to use jQuery UI's solution here, pickadate.js could also be a good choice, mobiscroll is a great but paid option. You can ultimately use whichever date picker you prefer for your needs.

Step 1: Add date picker assets

You'll first need to include the necessary assets from your datepicker library.

For the default example using jQuery UI, that includes a javascript and CSS file. We'll be using Google's CDN versions of the jQuery UI files, accessible from here. If you're using a different option, get the required javascript and CSS from their documentation.

To include it on your store, head to the “configuration” section of your store's FoxyCart administration. Look for the “Add custom header and footer code to your templates” option there, and include the javascript in the “custom footer” and CSS in the “custom header” textareas.

If you're already specifying a custom checkout template for your store - you can also directly include these assets in your custom checkout template.

Step 2: Add custom checkout field

You'll also need to add in your custom field, which can also be achieved from the “configuration” section of your store's FoxyCart administration. Look for the “Add custom form fields to your checkout” option and paste the following HTML there. If your store is enabled for multiship - and you need to capture the date for each different address, include it within the “custom multiship checkout fields” textarea. Otherwise include it in the “custom checkout fields” textarea.

<div class="fc-form-group">
	<div class="col-md-8 col-md-offset-3" data-fc-error-for="date-select" data-fc-error-class="fc-alert-container--error">
		<div class="fc-input-group-container fc-input-group-container--checkbox fc-input-group-container--active">
			<label class="fc-input-group-container__title fc-input-group-container__title--forced fc-form-label">Shipping date</label>
			<div class="fc-form-group date-select">
				<input class="fc-form-control" placeholder="Select a date" type="text" id="date-select" value="{{ ship_date }}" name="ship_date" aria-required="true" data-fc-required>
			</div>
		</div>
	</div>
</div>
If you update the name of the input (above as ship_date), you'll also need to update the Twig placeholder within the value to match. Also, avoid having the name start as shipping_, billing_ or shipto_ as it will interfere with storing the value clientside.

Step 3: Add javascript

Finally - you need to add some javascript to initialise the date picker library. This will happen within the same “Add custom header and footer code to your templates” option on the configuration section - but this time within the “footer” textarea.

jQuery UI

If you included the date picker field within the “custom checkout fields” textarea in step 2, you will use javascript like this:

{% if context == "checkout" %}
<script>
FC.client.on("render.done", initDatePicker);
 
function initDatePicker() {
    var date_params = {
        minDate: 0,
        onSelect: function() {
            $(this).trigger('focusout.fc', {validateNow: true});
        }
    };
 
    $("#date-select").datepicker(date_params);
};
</script>
{% endif %}

If you're running a multiship store and you included the datepicker field in the “custom multiship checkout fields” textarea, you'll use this javascript instead:

{% if context == "checkout" %}
<script>
FC.client.on("render.done", initDatePicker);
 
function initDatePicker() {
    var date_params = {
        minDate: 0,
        onSelect: function() {
            $(this).trigger('focusout.fc', {validateNow: true});
        }
    };
 
    if (FC.json.has_multiship) {
        for (var i = 0; i < FC.json.multiship_data.length; i++) {
            $("#shipto_custom_" + i + "_date-select']").datepicker(date_params);
        }
    } else {
        $("#date-select").datepicker(date_params);
    }
};
</script>
{% endif %}
You'll only use one of the above javascript blocks - depending on which approach you took in step 2.

In both the blocks above, a date_params object is created to set any custom properties for the date picker. Included in the code is a minDate property to restrict the picker to only dates in the future, and an onSelect event callback to ensure the selected rate is validated on the checkout. You can expand on that object with whatever settings you like.

pickadate.js

If you're using pickadate.js for your datepicker, here's an example of the javascript needed to incorporate it into the checkout:

{% if context == "checkout" %}
<script>
    FC.client.on("render.done", initDatePicker);
 
    function initDatePicker() {
        $('#date-select').pickadate({
            min: true,
            formatSubmit: 'yyyy-mm-dd',
            hiddenName: true,
            onSet: function (context) {
                var date_input = (this.$node.attr("name")) ? this.$node[0] : this._hidden;
                FC.json[date_input.name] = date_input.value;
                this.$node.trigger('focusout.fc', { validateNow: true });
            }
        });
    };
</script>
{% endif %}

Mobiscroll

If you're using Mobiscroll for your datepicker, here's an example of the javascript needed to incorporate it into the checkout:

{% if context == "checkout" %}
<script>
    FC.client.on("ready.done", initDatePicker);
    FC.client.on("render.done", function(params) {
        if (['checkout', 'additional_fields'].includes(params.block_id)) {
            initDatePicker();
        }
    });
 
    function initDatePicker() {
        $('#date-select').mobiscroll().datepicker({ 
            controls: ['date'],
            min: new Date(),
            onChange: function (event, inst) {
                $(inst.props.element).trigger('focusout.fc', { validateNow: true });
            }
        });
    };
</script>
{% endif %}

A Different Date Picker

If you're not using jQuery UI's datepicker, or one of the other options noted above, it should be fairly straight-forward for how you'd customise the relevant javascript there, but it'll basically revolve around updating the datepicker() function call(s). The jQuery UI example code above also includes a callback function for jQuery UI's onSelect event - because the way it handles it, it doesn't trigger the checkout's native validations to clear the error. Depending on the datepicker you use - you may need to also use a callback like that using their respective event that is run on select.

Step 4: Test!

At this point - everything should be set up and ready to go! You should be able to now load up your checkout and test out the new field - making sure that it's working as you expect.

Site Tools