Date validation

This guide will show you how to validate dates submitted in a Date element and also change the JavaScript datepicker options, so you can, for example, prevent certain dates from being chosen.

Step 1

Add a Date element to your form.

Step 2

Get the unique element ID for your Date element, see Finding the unique element ID.

Step 3

Add the following code to the wp-content/themes/YOUR_THEME/functions.php file (or create a plugin for it). In this file we’ll hook into the Quform plugin to change the datepicker options and validate the date. Add the PHP code from one of the examples below.

Prevent past dates from being chosen

1
2
3
4
5
6
7
8
9
10
11
1213
14
15
16
17
18
19
20
21
function my_prevent_past_dates($valid, $value, $element)
{
    $time = strtotime("{$value['year']}-{$value['month']}-{$value['day']}");
 
    if ($time < strtotime('today')) {
        $element->addError('Please choose a date in the future');
        $valid = false;
    }
 
    return $valid;
}
add_filter('iphorm_element_valid_iphorm_1_1', 'my_prevent_past_dates', 10, 3); 
function my_datepicker_prevent_past_dates($options, $dpMinYear, $dpMaxYear, $element)
{
    return "{
        minDate: 0,
        maxDate: new Date({$dpMaxYear}, 12 - 1, 31)
    }";
}
add_filter('iphorm_datepicker_options_iphorm_1_1', 'my_datepicker_prevent_past_dates', 10, 4);
function my_prevent_past_dates($valid, $value, $element)
{
    $time = strtotime("{$value['year']}-{$value['month']}-{$value['day']}");

    if ($time < strtotime('today')) {
        $element->addError('Please choose a date in the future');
        $valid = false;
    }

    return $valid;
}
add_filter('iphorm_element_valid_iphorm_1_1', 'my_prevent_past_dates', 10, 3);

function my_datepicker_prevent_past_dates($options, $dpMinYear, $dpMaxYear, $element)
{
    return "{
        minDate: 0,
        maxDate: new Date({$dpMaxYear}, 12 - 1, 31)
    }";
}
add_filter('iphorm_datepicker_options_iphorm_1_1', 'my_datepicker_prevent_past_dates', 10, 4);

Modify the highlighted lines to suit your form setup:

  • On lines 12 and 21, change iphorm_1_1 to the Date element unique ID, from Step 2.

Prevent specific dates from being chosen

Preventing specific dates is trickier, but still possible. We will need similar functions to the above but this time instead of checking if the date is in the past we need to check a predefined list of dates. First lets make a function to simply return a list of dates that we want to block so that we can re-use this in both the PHP validation and datepicker options functions. It’s important not to add any leading zeros to the month or day numbers in this list. Add any additional dates you want to disable as values in the array below.

1
2
3
4
5
6
7
8
function my_get_dates_to_disable()
{
    return array(
        '2012-10-1',
        '2012-2-28',
        '2012-3-25'
    );
}
function my_get_dates_to_disable()
{
    return array(
        '2012-10-1',
        '2012-2-28',
        '2012-3-25'
    );
}

Now, we need to make function to hook into the plugin at form validation time, check the submitted date against our list of disabled dates and display an error if it matches one of them. Be sure to replace iphorm_1_1 on line 15 with your unique Date element ID.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function my_prevent_specific_dates($valid, $value, $element)
{
    if ($valid) {
        $disabledDates = my_get_dates_to_disable();
        $submittedDate = "{$value['year']}-{$value['month']}-{$value['day']}";
 
        if (in_array($submittedDate, $disabledDates)) {
            $element->addError('That date is not available');
            $valid = false;
        }
    }
 
    return $valid;
}
add_filter('iphorm_element_valid_iphorm_1_1', 'my_prevent_specific_dates', 10, 3);
function my_prevent_specific_dates($valid, $value, $element)
{
    if ($valid) {
        $disabledDates = my_get_dates_to_disable();
        $submittedDate = "{$value['year']}-{$value['month']}-{$value['day']}";

        if (in_array($submittedDate, $disabledDates)) {
            $element->addError('That date is not available');
            $valid = false;
        }
    }

    return $valid;
}
add_filter('iphorm_element_valid_iphorm_1_1', 'my_prevent_specific_dates', 10, 3);

Next, we need to make a function that will hook into the plugin making the datepicker options and make a function that will block the selection of one of our dates. We also need to pass our dates through to the JavaScript so that we can check them, we can do this through the wp_head hook. Be sure to replace iphorm_1_1 on line 17 with your unique Date element ID.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1718
19
20
21
22
23
24
25
26
27
function my_datepicker_prevent_specific_dates($options, $dpMinYear, $dpMaxYear, $element)
{
    return "{
        beforeShowDay: function (date) {
            if (quformDisabledDates) {
                for (var i = 0; i < quformDisabledDates.length; i++) {
                    var parts = quformDisabledDates[i].split('-');
                    if (date.getFullYear() == parts[0] && (date.getMonth()+1) == parts[1] && date.getDate() == parts[2]) {
                        return [false];
                    }
                }
            }
            return [true];
        }
    }";
}
add_filter('iphorm_datepicker_options_iphorm_1_1', 'my_datepicker_prevent_specific_dates', 10, 4); 
function my_print_dates_to_disable()
{
    ?>
    <script type="text/javascript">
    var quformDisabledDates = <?php echo json_encode(my_get_dates_to_disable()); ?>;
    </script>
    <?php
}
add_action('wp_head', 'my_print_dates_to_disable');
function my_datepicker_prevent_specific_dates($options, $dpMinYear, $dpMaxYear, $element)
{
    return "{
        beforeShowDay: function (date) {
            if (quformDisabledDates) {
                for (var i = 0; i < quformDisabledDates.length; i++) {
                    var parts = quformDisabledDates[i].split('-');
                    if (date.getFullYear() == parts[0] && (date.getMonth()+1) == parts[1] && date.getDate() == parts[2]) {
                        return [false];
                    }
                }
            }
            return [true];
        }
    }";
}
add_filter('iphorm_datepicker_options_iphorm_1_1', 'my_datepicker_prevent_specific_dates', 10, 4);

function my_print_dates_to_disable()
{
    ?>
    <script type="text/javascript">
    var quformDisabledDates = <?php echo json_encode(my_get_dates_to_disable()); ?>;
    </script>
    <?php
}
add_action('wp_head', 'my_print_dates_to_disable');

Note that the datepicker options hooks will not inherit the options from any previous hooks. So if you plan on using both steps above to block past dates and specific dates, you should move the datepicker options into one function.

Booking system

To extend the above functionality and make a simple booking system there are a couple of extra things you need to do. Firstly, save the chosen date when the form is successfully submitted. Secondly, change the array of blocked dates to pull the saved dates from the database instead.

Step 1

Read the above section Prevent specific dates from being chosen and add all the code from that section.

Step 2

Create a new database table in your WordPress database with one column named date of type VARCHAR (10). Name the table wp_bookings.

Step 3

Add the new PHP function below to which will run when the form is successfully submitted.

1
2
3
4
56
7
8
9
10
11
function my_save_booking_date($form)
{
    global $wpdb;
 
    $date = $form->getValue('iphorm_3_1'); 
    $wpdb->insert('wp_bookings', array(
        'date' => $date['year'] . '-' . $date['month'] . '-' . $date['day']
    ));
}
add_action('iphorm_post_process_3', 'my_save_booking_date', 10, 1);
function my_save_booking_date($form)
{
	global $wpdb;

	$date = $form->getValue('iphorm_3_1');

	$wpdb->insert('wp_bookings', array(
		'date' => $date['year'] . '-' . $date['month'] . '-' . $date['day']
	));
}
add_action('iphorm_post_process_3', 'my_save_booking_date', 10, 1);
  • On line 5, change iphorm_3_1 to your date element unique ID.
  • On line 11, change the number 3 on the first line to your form ID, see Finding the form ID.

Step 4

Modify the function my_get_dates_to_disable that you added in Step 1 by replacing it with the code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function my_get_dates_to_disable()
{
    global $wpdb;
 
    $dates = $wpdb->get_results('SELECT `date` FROM wp_bookings;', ARRAY_A);
    $disabledDates = array();
 
    if (is_array($dates)) {
        foreach ($dates as $date) {
            $disabledDates[] = $date['date'];
        }
    }
 
    return $disabledDates;
}
function my_get_dates_to_disable()
{
	global $wpdb;

	$dates = $wpdb->get_results('SELECT `date` FROM wp_bookings;', ARRAY_A);
	$disabledDates = array();

	if (is_array($dates)) {
		foreach ($dates as $date) {
			$disabledDates[] = $date['date'];
		}
	}

	return $disabledDates;
}

Blocking entire days

If there are specific days every week that you want to block, there are 2 things we must do. We will need your Date element unique ID, to find this, use this guide. Firstly, configure the Datepicker script to prevent these days from being chosen. Secondly we must create a form validation function to prevent the form being submitted if one of these days are chosen. Both code samples are shown below, in this example we will block the days Saturday and Sunday.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1516
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function my_datepicker_block_days($options, $dpMinYear, $dpMaxYear, $element)
{
    return "{
        beforeShowDay: function (date) {
            var day = date.getDay();
            if (day == 0 || day == 6) {
                // It's a Sunday or Saturday, block the date
                return [false, ''];
            } else {
                return [true, ''];
            }
        }
    }";
}
add_filter('iphorm_datepicker_options_iphorm_1_1', 'my_datepicker_block_days', 10, 4); 
function my_block_days($valid, $value, $element)
{
    if ($valid) {
        $time = strtotime("{$value['year']}-{$value['month']}-{$value['day']}");
        $day = date('w', $time);
 
        if ($day == 0 || $day == 6) {
            $element->addError('Please choose another day');
            $valid = false;
        }
    }
 
    return $valid;
}
add_filter('iphorm_element_valid_iphorm_1_1', 'my_block_days', 10, 3);
function my_datepicker_block_days($options, $dpMinYear, $dpMaxYear, $element)
{
    return "{
        beforeShowDay: function (date) {
            var day = date.getDay();
            if (day == 0 || day == 6) {
                // It's a Sunday or Saturday, block the date
                return [false, ''];
            } else {
                return [true, ''];
            }
        }
    }";
}
add_filter('iphorm_datepicker_options_iphorm_1_1', 'my_datepicker_block_days', 10, 4);

function my_block_days($valid, $value, $element)
{
    if ($valid) {
        $time = strtotime("{$value['year']}-{$value['month']}-{$value['day']}");
        $day = date('w', $time);

        if ($day == 0 || $day == 6) {
            $element->addError('Please choose another day');
            $valid = false;
        }
    }

    return $valid;
}
add_filter('iphorm_element_valid_iphorm_1_1', 'my_block_days', 10, 3);
  • On lines 15 and 31, change iphorm_1_1 to your date element unique ID.

Validating a date against another form value

If you have two date elements in your form you can validate one of the dates against the value of the other, so you could make sure one date is always later than the other. You will need the unique identifier for both of your date elements. To get this see Step 2 at the top of this page. In this example I will have “start date” and “end date” fields which will be common in a booking system. Add the code below as described in Steps 3 & 4 above.

1
2
3
45
6
7
8
9
10
11
12
13
14
15
16
function my_check_date_range($valid, $value, $element)
{
    // Get the value of the start date element
    $startDate = $element->getForm()->getValue('iphorm_1_1'); 
    $startDate = strtotime("{$startDate['year']}-{$startDate['month']}-{$startDate['day']} 00:00:00");
    $endDate = strtotime("{$value['year']}-{$value['month']}-{$value['day']} 23:59:59");
 
    if ($startDate > $endDate) {
        $element->addError('The end date must be after the start date');
        $valid = false;
    }
 
    return $valid;
}
add_filter('iphorm_element_valid_iphorm_1_2', 'my_check_date_range', 10, 3);
function my_check_date_range($valid, $value, $element)
{
    // Get the value of the start date element
    $startDate = $element->getForm()->getValue('iphorm_1_1');

    $startDate = strtotime("{$startDate['year']}-{$startDate['month']}-{$startDate['day']} 00:00:00");
    $endDate = strtotime("{$value['year']}-{$value['month']}-{$value['day']} 23:59:59");

    if ($startDate > $endDate) {
        $element->addError('The end date must be after the start date');
        $valid = false;
    }

    return $valid;
}
add_filter('iphorm_element_valid_iphorm_1_2', 'my_check_date_range', 10, 3);
  • On line 4, change iphorm_1_1 to your “Start Date” element unique ID.
  • On line 16, change iphorm_1_2 to your “End Date” element unique ID.

This code will make the form now display an error under the end date if it is before the start date and it will prevent the form being submitted. If you notice that there are times at the end of the line of code that calculates the dates precisely, this makes it valid for the start date and end date to be the same date.

Still having trouble? Head over to the forums.

Forums