Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

limit DATE fields in Elementor Forms #6372

Closed
Talco100 opened this issue Dec 7, 2018 · 75 comments
Closed

limit DATE fields in Elementor Forms #6372

Talco100 opened this issue Dec 7, 2018 · 75 comments
Labels
type/developer-api Indicates when a topic is related to the Developer API and Documentation. widget/forms References the Form (Pro) widget and its features.

Comments

@Talco100
Copy link

Talco100 commented Dec 7, 2018

Prerequisites

  • [x ] I have searched for similar features requests in both open and closed tickets and cannot find a duplicate.
  • [ x] The feature is still missing in the latest stable version of Elementor ( Elementor Pro. )

What problem is your feature request going to solve? Please describe.
An option to limit a DATE field in Elementor Forms so the user will not be able to enter a date younger than X (parameter) days after today.
i.e. if today is December 20th, user will be able to choose dates from December 27th and so on until the end of time...

Describe the solution you'd like
a place to choose the type of the limit (max/min), and a specific date, or number of days from today (which is fluid).

Describe alternatives you've considered
A ready made JS code?

Additional context

@bainternet
Copy link
Contributor

@Talco100

Well first you should set the server side validation:

// Validate the date field min value to 7 days ago and max value to 7 days from today.
add_action( 'elementor_pro/forms/validation/date', function( $field, $record, $ajax_handler ) {

	// make sure ts the correct date field
	if ( 'YOUR_FIELD_ID' === $field['id'] ) {
		return;
	}

	$min_allowed_date = strtotime( '-7 day' );
	$max_allowed_date = strtotime( '+7 day' );


	$form_date = strtotime( $field['value'] );
	if ( $min_allowed_date > $form_date ) {
		$ajax_handler->add_error( $field['id'], 'The Minimum allowed date is, ' . date( 'Y-M-d', $min_allowed_date ) );
	}
	if ( $max_allowed_date < $form_date ) {
		$ajax_handler->add_error( $field['id'], 'The Maximum allowed date is, ' . date( 'Y-M-d', $max_allowed_date ) );
	}
}, 10, 3 );

look closly at these lines:

$min_allowed_date = strtotime( '-7 day' );
$max_allowed_date = strtotime( '+7 day' );

in this example we validate the the date must be between 7 days ago and 7 days from today, but you can easly change that to anything else.

And as for the JavaScript date picker (flatpickr)

here is a little Helper I wrote:

var limitFlatPicker = limitFlatPicker || {};
jQuery( document ).ready( function( $ ){
	limitFlatPicker = {
		defaultSettings: {
			selector: '.flatpickr-input',
			minDate: false,
			maxDate: false,
		},
		settings: {},
		init: function( options ) {
			this.settings = $.extend( this.defaultSettings, options );
			if ( this.settings.minDate || this.settings.maxDate ) {
				this.waitForFlatpicker( this.callback );
			}
		},
		waitForFlatpicker: function( callback ) {
			if ( typeof window.flatpickr !== 'function' ) {
				setTimeout( function() { limitFlatPicker.waitForFlatpicker( callback ) }, 100 );
			}
			callback();
		},
		modifyPicker: function( picker, settings ) {
			flatpickr( picker ).set( settings );
		},
		callback: function() {
			var self = limitFlatPicker;
			$( self.settings.selector ).each( function() {
				var picker = $( this )[0],
					pickerSettings = {};

				if ( self.settings.minDate ) {
					pickerSettings['minDate'] = self.settings.minDate;
				}
				if ( self.settings.maxDate ) {
					pickerSettings['maxDate'] = self.settings.maxDate;
				}
				self.modifyPicker( picker, pickerSettings );
			} );
		}
	}
} );

and to use it you simple call it with the dates you want:

var aWeekAgo = new Date(),
	aWeekFromToday = new Date();
aWeekAgo.setDate( aWeekAgo.getDate() - 7 );
aWeekFromToday.setDate( aWeekFromToday.getDate() + 7 );

limitFlatPicker.init( {
	minDate: aWeekAgo,
	maxDate: aWeekFromToday
} );

8tkqalv

Just make sure you enclude the JS on the correct page, could be easly done via your functions.php

add_action( 'wp_footer', function() {
	if ( ! is_page( YOUR_PAGE_ID_HERE ) ) {
		return;
	}
	?>
	<script>//JS CODE HERE</script>
	<?php
} );

Good luck.

@bainternet bainternet added type/developer-api Indicates when a topic is related to the Developer API and Documentation. widget/forms References the Form (Pro) widget and its features. labels Dec 9, 2018
@Talco100
Copy link
Author

Hi
Any change this feature will be added to Elementor? (to be accessible without coding)
Thanks
Tal

@dasignlady
Copy link

Would LOVE this feature non-coded. Currently using 4 extra plugins: CF7, CF7DB (for collecting csv data), Column Shortcodes( to make fields side-by-side), and Contact Form 7 Shortcode Enabler (for integration of previous) for the stupid calendar restriction. Thanks for the code. Gonna try it someday.

@odedta
Copy link

odedta commented Jun 26, 2019

Hello,
Just sharing... if the above code doesn't work for you, try wrapping the call to picker with a timeout as follows:

setTimeout( function() {
    limitFlatPicker.init( {
        minDate: aWeekAgo,
	maxDate: aWeekFromToday
    } );
 }, 100 );

@odedta
Copy link

odedta commented Jul 18, 2019

@Talco100

Well first you should set the server side validation:

// Validate the date field min value to 7 days ago and max value to 7 days from today.
add_action( 'elementor_pro/forms/validation/date', function( $field, $record, $ajax_handler ) {

	// make sure ts the correct date field
	if ( 'YOUR_FIELD_ID' === $field['id'] ) {
		return;
	}

	$min_allowed_date = strtotime( '-7 day' );
	$max_allowed_date = strtotime( '+7 day' );


	$form_date = strtotime( $field['value'] );
	if ( $min_allowed_date > $form_date ) {
		$ajax_handler->add_error( $field['id'], 'The Minimum allowed date is, ' . date( 'Y-M-d', $min_allowed_date ) );
	}
	if ( $max_allowed_date < $form_date ) {
		$ajax_handler->add_error( $field['id'], 'The Maximum allowed date is, ' . date( 'Y-M-d', $max_allowed_date ) );
	}
}, 10, 3 );

look closly at these lines:

$min_allowed_date = strtotime( '-7 day' );
$max_allowed_date = strtotime( '+7 day' );

in this example we validate the the date must be between 7 days ago and 7 days from today, but you can easly change that to anything else.

And as for the JavaScript date picker (flatpickr)

here is a little Helper I used:

var limitFlatPicker = limitFlatPicker || {};
jQuery( document ).ready( function( $ ){
	limitFlatPicker = {
		defaultSettings: {
			selector: '.flatpickr-input',
			minDate: false,
			maxDate: false,
		},
		settings: {},
		init: function( options ) {
			this.settings = $.extend( this.defaultSettings, options );
			if ( this.settings.minDate || this.settings.maxDate ) {
				this.waitForFlatpicker( this.callback );
			}
		},
		waitForFlatpicker: function( callback ) {
			if ( typeof window.flatpickr !== 'function' ) {
				setTimeout( function() { limitFlatPicker.waitForFlatpicker( callback ) }, 100 );
			}
			callback();
		},
		modifyPicker: function( picker, settings ) {
			flatpickr( picker ).set( settings );
		},
		callback: function() {
			var self = limitFlatPicker;
			$( self.settings.selector ).each( function() {
				var picker = $( this )[0],
					pickerSettings = {};

				if ( self.settings.minDate ) {
					pickerSettings['minDate'] = self.settings.minDate;
				}
				if ( self.settings.maxDate ) {
					pickerSettings['maxDate'] = self.settings.maxDate;
				}
				self.modifyPicker( picker, pickerSettings );
			} );
		}
	}
} );

and to use it you simply call it with the dates you want:

var aWeekAgo = new Date(),
	aWeekFromToday = new Date();
aWeekAgo.setDate( aWeekAgo.getDate() - 7 );
aWeekFromToday.setDate( aWeekFromToday.getDate() + 7 );

limitFlatPicker.init( {
	minDate: aWeekAgo,
	maxDate: aWeekFromToday
} );

8tkqalv

Just make sure you include the JS on the correct page, could be easily done via your functions.php or in your external scripts file.

add_action( 'wp_footer', function() {
	if ( ! is_page( YOUR_PAGE_ID_HERE ) ) {
		return;
	}
	?>
	<script>//JS CODE HERE</script>
	<?php
} );

Good luck.

How can I use localization with the example you wrote?
I tried adding the translation file using:
wp_enqueue_script( 'flatpickr-he-js', get_stylesheet_directory_uri() . '/js/he.js', array( 'flatpickr-js' ) );

Then adding 'locale': 'he', to defaulSettings, didn't work, tried to add to init instead, didn't work. Please help.

@matteodapolito
Copy link

where i write this code? Location?!

@mrleonz
Copy link

mrleonz commented Apr 24, 2020

Tried to edit in Childtheme -> Functions.php
Doesn't work for me?

What i need to replace???

@odedta
Copy link

odedta commented Apr 24, 2020

All the JS code can go into where I wrote <script>//JS CODE HERE</script>. What exactly isn't working? what are you trying to do? can you post picture of your developer console to see if you have any errors?

@dasignlady
Copy link

dasignlady commented Apr 24, 2020

Forgive me for being obtuse. I am using Elementor Pro (precisely because I am not a backend developer. So all this code-speak is confusing without hand holding for this noob.)

Would you kindly explain for me what parts of the above JavaScript can be used in the Elementor Page itself using the HTML widget?

And, which part I must use with a Header/Footer code-injection plugin.

**How would you write the code to reflect this scenario: (and precisely, where does each part go)

Form Element Date picker 1.
User puts in Start Date (field ID-'start_date') which can be today or any day in the future

Form Element Date Picker 2.
User puts in End Date (field ID-'end_date') which CANNOT EXCEED +20 DAYS from 'start_date'.**

This is used in a Guest Pass form where it will be issued up to no more than 21 days total. Even though it says "Maximum 21 Days", people still put in whatever dates they want and I have to manually correct the submission...grrrr.

((The thing I don't understand with the Elementor Date Picker widget is why would you have a min/max date that you have to pick on the calendar instead of this +/- date parameter so it can be evergreen, like what I am looking for.))

Thank you in advance for your help!

guest-pass-form

@odedta
Copy link

odedta commented Apr 24, 2020

Hi @dasignlady
Since this feature is not available in the Editor, we have to use code to make this work, here are steps:

  1. You create a form with 2 date fields, make sure you set the date field id:
    Screenshot_3

  2. Paste this piece of code in your functions.php file in your child theme preferably.

/*
 * Limit datepicker `date_to` to maximum 21 days from date picked in `date_to`
 */
add_action( 'elementor_pro/forms/validation/date', function( $field, $record, $ajax_handler ) {
	if( 'date_to' === $field['id'] ) {
		$field_date 		= strtotime( $field['value'] );
		$max_allowed_date 	= strtotime( '+21 day' );
		
		if ( $max_allowed_date > $form_date ) {
			$ajax_handler->add_error( $field['id'], 'The Maximum allowed date is, ' . date( 'Y-M-d', $max_allowed_date ) );
		}
	}
}, 10, 3 );

This will ensure we are validating the date field on the server side:
Screenshot_8

Now we need to take care of the front-end validation and create better UX (User experience).

  1. As for the previous solution, I tried to make it work for this example but it didn't and since I don't want to spend too much time on this (:-P) I wrote a "workaround" to get this to work, you can paste this code in a plugin that injects Javascript code like Insert Headers and Footers:
jQuery( document ).ready( function( $ ) {
	setTimeout(
		function() {
			let today = new Date();
			let twentyOneDaysFromToday = new Date();
				
			today.setDate( today.getDate() );
			twentyOneDaysFromToday.setDate( twentyOneDaysFromToday.getDate() + 21 );
				
			let options = {
				minDate: today,
				maxDate: twentyOneDaysFromToday,
			};
				
			flatpickr( "#form-field-date_to", options );
		},
		500
	);
} );

This will essentially limit the datepicker to dates from "today" to "21 days from today"
Screenshot_6
Screenshot_7

If for some reason this doesn't work you can change the number 500 in the Javascript code to higher value like 1000 for example, this makes sure the load the code after the date picker has been initialized, there is a better way to solve this (bainternet's code).

Enjoy!

@dasignlady
Copy link

@odedta Wow! Thank you so much for your fast and detailed reply!!!
I will try this on a staging site since I have not implemented a child theme on the site currently up.
Again...Many Thanks!

@maisnovo
Copy link

maisnovo commented May 6, 2020

Hi @odedta or @bainternet

I need a code to define previous date date (today)

My business offers cleaning services.

Please tell me where I put the code please :)

Thanks in advance

@odedta
Copy link

odedta commented May 6, 2020

Hi @maisnovo
I wrote a very detailed post how to make this work... #6372 (comment)

@maisnovo
Copy link

maisnovo commented May 7, 2020

Thanks @odedta. Unfortunately dont work for me

Past the code on functions.php and jquery on footer widget

@odedta
Copy link

odedta commented May 7, 2020

Thanks @odedta. Unfortunately dont work for me

Past the code on functions.php and jquery on footer widget

PM on Facebook, i'll try to help when I can.

@Ricarditu
Copy link

Hi!
Still no news on this as a no-code-needed feature? It would also be cool to filter by week day.
Thanks!

@JessDelAngel
Copy link

JessDelAngel commented Jun 9, 2020

I think the condition to validate the correct date field should be as follow:

// make sure ts the correct date field
if ( 'YOUR_FIELD_ID' !== $field['id'] ) {
	return;
}

@ashkan-ahmadi
Copy link

This seems unnecessarily complicated when it should be added to the core functionality of Elementor. Most people use the date field to either pick something only in the future or only in the past or within a certain period so it should be part of Elementor. Otherwise, it's mostly useless

@ashkan-ahmadi
Copy link

I just figured this out and I thought it would be useful for everyone because I haven't managed to find an easy solution other than adding PHP code to the functions.php. By default it's not possible to set limits or formatting to the date form fields. There is a small library called Flatpickr.js that can help with this.
If you are using the Elementor Hello theme, you can do it right away, if not, you will need to do an extra step (read below):

You are using a theme that doesn't load Flatpick.js automatically:
If you want the library to run on all the pages, then you can load the library and its stylesheet through your functions.php, or adding an HTML code inside your footer with the code below:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>

You can also add the HTML code right after any form your want to target so that it doesn't run on every page.
After that, you just need to follow the same steps as below.

You are using the Hello theme:
The Hello theme by default runs the Flatpickr.js library on every page so you don't need to install it.

  1. Create a form and add a date field and give it an ID (e.g. FIELD_ID)
  2. Add an HTML after the form and add the following code:
<script>
     window.addEventListener('DOMContentLoaded', () => {
    flatpickr("#form-field-FIELD_ID", {
        // custom code goes here
    });
});
</script>

You then need to replace the FIELD_ID with your own ID and the 4th line with all the custom parameters you can find on Flatpick.js's website: https://flatpickr.js.org/examples/ The code is wrapped in a DOMContentLoaded event because the Hello theme runs the library from the footer so the code won't be able to run before it has been loaded.
Here is a basic example I have made: https://studentfytrips.com/test-flatpickr/
Here I have added the code minDate: "today" so the date picker doesn't allow the user to pick any date in the past. If you want multiple parameters, then separate them with a comma.

So far this is the simplest method I have found. I hope it helped you.

@alexplex
Copy link

@ashkan-ahmadi

Thanks! This is brilliant. But I think I'm experiencing a bug. The first second of loading my page it does work with both mode and minDate. But after one second the datepicker kind of reloads and the script won't work. I'm using the Hello Theme also.

@ashkan-ahmadi
Copy link

Hi @alexplex

That's strange. Try to create a new page with nothing else on it, just a form, and then try again. Also look at the Console to see if you are getting any error related to Flatpickr.js

@alexplex
Copy link

alexplex commented Aug 26, 2020

@ashkan-ahmadi Same on a new test page. I'm not getting any error in the console. It almost feels like it loads everything correctly the first second but then a second later something else loads, perhaps in the footer, and resets the script.

Here you can have a look at the source code if you want :)
https://pastebin.com/sgBd0fAD

Tried to deactivate all plugins. Nothing.

@ashkan-ahmadi
Copy link

That's strange. Try changing the theme and loading the library before the form and then DOMContentLoaded event after the form.

I just reviewed the code, it's most probably the script from line 248 to 254 doing this resetting this after 1 second. I'm not how that was added though because I don't have this on my own pages. If you added that, delete it.

@ashkan-ahmadi
Copy link

Hi, can i check how do i block off selected days, example sunday, for the elementor form?

Yes. You can see everything you can do here: https://flatpickr.js.org/examples/ (Disabling dates by a function)

@NicFindlay
Copy link

@odedta , used your code;

jQuery( document ).ready( function( $ ) {
setTimeout(
function() {
let today = new Date();
let twentyOneDaysFromToday = new Date();

		today.setDate( today.getDate() );
		twentyOneDaysFromToday.setDate( twentyOneDaysFromToday.getDate() + 21 );
			
		let options = {
			minDate: today,
			maxDate: twentyOneDaysFromToday,
		};
			
		flatpickr( "#form-field-date_to", options );
	},
	500
);

} );

How to block the weekends as well! so i can use it for my appointment calendar

Thank you, this is literally the only code on this thread that worked

@DutchGuyQuestion
Copy link

DutchGuyQuestion commented May 17, 2021

complete code including blocked weekends!

<script>jQuery( document ).ready( function( $ ) {
	setTimeout(
		function() {
			let plusFourDays = new Date();
			let eightTeenDaysFromToday = new Date();
			
			plusFourDays.setDate( plusFourDays.getDate() + 4 );
			eightTeenDaysFromToday.setDate( eightTeenDaysFromToday.getDate() + 18 );
			
			let options = {
				minDate: plusFourDays,
				disable: [
					function( date ) {
						return ( date.getDay() === 0 || date.getDay() === 6 );
					}
				],
				locale: { "firstDayOfWeek": 1 },
				maxDate: eightTeenDaysFromToday,
			};
			
			flatpickr( "#form-field-YOUR_ID", options );
		},
		500
	);
} );
</script>

@immu2018
Copy link

immu2018 commented Nov 18, 2021

can i have a code to just disable past dates only , code i can put in elementor code section

in the DATE FIELD how do i set min date to 0 - it is not allowing me to set to 0 so that past dates can be disable

your help is much appreciated - i am using elementor pro as well

@ashkan-ahmadi
Copy link

Apparently, something in Elementor has changed and now if you are using the code I added last year does not work. For some reason (would be cool if someone has the patience to figure out why), the Flatpickr library finishes loading after DOMContentLoaded. A quick fix is to add the flatpickr function inside a setTimeout() function with a 500ms (or 1000ms) delay. For example:

window.addEventListener('DOMContentLoaded', () => {
   setTimeout(() => {
       flatpickr("#form-field-FIELD_ID", {
           // custom code goes here
       });
   }, 500) // 500ms. change to 1000 for 1 second
});

@ashkan-ahmadi
Copy link

@immu2018 No, you can't use the Code widget. That's not for running a code, that's for displaying a code (like how you see the code below). You need to use the HTML widget. To make the previous dates disabled, you need to copy-paste the following code in an HTML widget on the same page as your form (below it would be best). The minDate: "today" part means the minimum date has to be today. Make sure you change FIELD_ID to your input field id (do not remove #form-field- all form fields in Elementor begin with form-field- in the DOM.

<script>
window.addEventListener('DOMContentLoaded', () => {
   setTimeout(() => {
       flatpickr("#form-field-FIELD_ID", {
            minDate: "today"
       });
   }, 500) // 500ms. change to 1000 for 1 second
});
</script>

@immu2018
Copy link

i would like to thank you and appreciate you for the fast reply you have given to my issue - i hope you progress in your life and career

@namazty
Copy link

namazty commented Dec 13, 2021

@immu2018 No, you can't use the Code widget. That's not for running a code, that's for displaying a code (like how you see the code below). You need to use the HTML widget. To make the previous dates disabled, you need to copy-paste the following code in an HTML widget on the same page as your form (below it would be best). The minDate: "today" part means the minimum date has to be today. Make sure you change FIELD_ID to your input field id (do not remove #form-field- all form fields in Elementor begin with form-field- in the DOM.

<script>
window.addEventListener('DOMContentLoaded', () => {
   setTimeout(() => {
       flatpickr("#form-field-FIELD_ID", {
            minDate: "today"
       });
   }, 500) // 500ms. change to 1000 for 1 second
});
</script>

@ashkan-ahmadi
Thank you bro! it works well.
I have another issue. I need also to disable every Sunday of elementor form. Coudl you advise me, please?

@ashkan-ahmadi
Copy link

ashkan-ahmadi commented Dec 13, 2021

Hi @namazty
No worries. You can simply use this code (don't feel intimidated by its length).

<script>
  window.addEventListener("DOMContentLoaded", () => {
    const daysOfTheWeek = {
      Monday: 1,
      Tuesday: 2,
      Wednesday: 3,
      Thursday: 4,
      Friday: 5,
      Saturday: 6,
      Sunday: 0
    };
    setTimeout(() => {
      flatpickr("#form-field-FIELD_ID", {
        minDate: "today",
        locale: {
          firstDayOfWeek: daysOfTheWeek["Monday"]
        },
        disable: [
          function (date) {
            return (
              date.getDay() === daysOfTheWeek["Sunday"]
            ) // add like daysOfTheWeek['Monday'] separated by || (no leading ||)
          }
        ]
      });
    }, 500); // 500ms. change to 1000 for 1 second
  });
</script>

Here are the params you can modify in the code:

  • minDate blocks every day older than today
  • firstDayOfWeek starts the day on Monday. For example, you can change daysOfTheWeek["Monday"] to daysOfTheWeek["Saturday"] if you want the week to start from Saturdays
  • date.getDay() === daysOfTheWeek["Sunday"] means block every Sunday. If you want to block multiple days (for example, Sundays and Mondays), then repeat that whole code separate by || (example: date.getDay() === daysOfTheWeek["Sunday"] || date.getDay() === daysOfTheWeek["Monday"]

Remember: you can see all the examples here: https://flatpickr.js.org/examples/ (you can mix and match anything you need)

@chicoco07
Copy link

Why is this closed? We don't get elementor pro to use code.

@raabmar
Copy link

raabmar commented Mar 29, 2022

Hi @namazty No worries. You can simply use this code (don't feel intimidated by its length).

Hey, I tested this and it worked for me on Elementor 3.5.6.
However, what actually would make sense to prevent the visitor from selecting a to-date that lies before the from-date

e.g., what I would like to get the following with 2 datepicker entries

FROM_DATE = > (today + 5 days)
TILL_DATE = > (FROM_DATE + 7 days)

In English that would mean booking only allowed from 5 days from today and minimum stay is 7 days.
Sounds complicated, but I thought that must be quite basic. Too bad that there are still no settings in Elementor form.

@samwzirong
Copy link

samwzirong commented May 10, 2022

Hi @namazty No worries. You can simply use this code (don't feel intimidated by its length).

<script>
  window.addEventListener("DOMContentLoaded", () => {
    const daysOfTheWeek = {
      Monday: 1,
      Tuesday: 2,
      Wednesday: 3,
      Thursday: 4,
      Friday: 5,
      Saturday: 6,
      Sunday: 0
    };
    setTimeout(() => {
      flatpickr("#form-field-FIELD_ID", {
        minDate: "today",
        locale: {
          firstDayOfWeek: daysOfTheWeek["Monday"]
        },
        disable: [
          function (date) {
            return (
              date.getDay() === daysOfTheWeek["Sunday"]
            ) // add like daysOfTheWeek['Monday'] separated by || (no leading ||)
          }
        ]
      });
    }, 500); // 500ms. change to 1000 for 1 second
  });
</script>

Here are the params you can modify in the code:

  • minDate blocks every day older than today
  • firstDayOfWeek starts the day on Monday. For example, you can change daysOfTheWeek["Monday"] to daysOfTheWeek["Saturday"] if you want the week to start from Saturdays
  • date.getDay() === daysOfTheWeek["Sunday"] means block every Sunday. If you want to block multiple days (for example, Sundays and Mondays), then repeat that whole code separate by || (example: date.getDay() === daysOfTheWeek["Sunday"] || date.getDay() === daysOfTheWeek["Monday"]

Remember: you can see all the examples here: https://flatpickr.js.org/examples/ (you can mix and match anything you need)

Thank you for this code. I did exactly what you mention. As in putting the HTML code after the form. I do need some help. How do I tell flatpickr is workiong? My form doesn't seem to start on Monday and the Saturdays are not grey out.

From the breakpoint, I do know the setTimeout is being triggered but nothing seems to be working.

@ashkan-ahmadi
Copy link

Hi @samwzirong. The most common reason is not adding the right field ID. If your page is live, share the link and i will check it. If not, simply write the ID of the date field and I will give you the exact code to copy-paste

@samwzirong
Copy link

Hi @samwzirong. The most common reason is not adding the right field ID. If your page is live, share the link and i will check it. If not, simply write the ID of the date field and I will give you the exact code to copy-paste

Hi @ashkan-ahmadi thank you! Oh wait it's working! I was about to send you the link and noticed it's working now. Most likely it's a cache issue.

@MariaAlbuq
Copy link

Hey! I did everything as you explained and nothing happened!
what am I doing wrong??

this is the code i wrote in the end of functions.php file
`
add_action( 'elementor_pro/forms/validation/date', function( $field, $record, $ajax_handler ) {
if ( 'field_c835856' === $field['id'] ) {
return;
}

$min_allowed_date = strtotime( '-7 day' );
$max_allowed_date = strtotime( '+7 day' );


$form_date = strtotime( $field['value'] );
if ( $min_allowed_date > $form_date ) {
	$ajax_handler->add_error( $field['id'], 'The Minimum allowed date is, ' . date( 'Y-M-d', $min_allowed_date ) );
}
if ( $max_allowed_date < $form_date ) {
	$ajax_handler->add_error( $field['id'], 'The Maximum allowed date is, ' . date( 'Y-M-d', $max_allowed_date ) );
}

}, 10, 3 );

add_action( 'wp_footer', function() {
if ( ! is_page( 350 ) ) {
return;
}
?>
<script>
var limitFlatPicker = limitFlatPicker || {};
jQuery( document ).ready( function( $ ){
limitFlatPicker = {
defaultSettings: {
selector: '.flatpickr-input',
minDate: false,
maxDate: false,
},
settings: {},
init: function( options ) {
this.settings = $.extend( this.defaultSettings, options );
if ( this.settings.minDate || this.settings.maxDate ) {
this.waitForFlatpicker( this.callback );
}
},
waitForFlatpicker: function( callback ) {
if ( typeof window.flatpickr !== 'function' ) {
setTimeout( function() { limitFlatPicker.waitForFlatpicker( callback ) }, 100 );
}
callback();
},
modifyPicker: function( picker, settings ) {
flatpickr( picker ).set( settings );
},
callback: function() {
var self = limitFlatPicker;
$( self.settings.selector ).each( function() {
var picker = $( this )[0],
pickerSettings = {};

			if ( self.settings.minDate ) {
				pickerSettings['minDate'] = self.settings.minDate;
			}
			if ( self.settings.maxDate ) {
				pickerSettings['maxDate'] = self.settings.maxDate;
			}
			self.modifyPicker( picker, pickerSettings );
		} );
	}
}

} );
var aWeekAgo = new Date(),
aWeekFromToday = new Date();
aWeekAgo.setDate( aWeekAgo.getDate() - 7 );
aWeekFromToday.setDate( aWeekFromToday.getDate() + 7 );

limitFlatPicker.init( {
minDate: aWeekAgo,
maxDate: aWeekFromToday
} );
</script>
<?php
} );`

@Oaufi
Copy link

Oaufi commented Aug 17, 2022

I just figured this out and I thought it would be useful for everyone because I haven't managed to find an easy solution other than adding PHP code to the functions.php. By default it's not possible to set limits or formatting to the date form fields. There is a small library called Flatpickr.js that can help with this.
If you are using the Elementor Hello theme, you can do it right away, if not, you will need to do an extra step (read below):

You are using a theme that doesn't load Flatpick.js automatically:
If you want the library to run on all the pages, then you can load the library and its stylesheet through your functions.php, or adding an HTML code inside your footer with the code below:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>

You can also add the HTML code right after any form your want to target so that it doesn't run on every page.
After that, you just need to follow the same steps as below.

You are using the Hello theme:
The Hello theme by default runs the Flatpickr.js library on every page so you don't need to install it.

  1. Create a form and add a date field and give it an ID (e.g. FIELD_ID)
  2. Add an HTML after the form and add the following code:
<script>
     window.addEventListener('DOMContentLoaded', () => {
    flatpickr("#form-field-FIELD_ID", {
        // custom code goes here
    });
});
</script>

You then need to replace the FIELD_ID with your own ID and the 4th line with all the custom parameters you can find on Flatpick.js's website: https://flatpickr.js.org/examples/ The code is wrapped in a DOMContentLoaded event because the Hello theme runs the library from the footer so the code won't be able to run before it has been loaded.
Here is a basic example I have made: https://studentfytrips.com/test-flatpickr/
Here I have added the code minDate: "today" so the date picker doesn't allow the user to pick any date in the past. If you want multiple parameters, then separate them with a comma.

So far this is the simplest method I have found. I hope it helped you.

That's perfect, Thanks. Any idea how to html for Elementor for tel filed to accept only numbers and 8 digit?

@ashkan-ahmadi
Copy link

Any idea how to html for Elementor for tel filed to accept only numbers and 8 digit?

The Flatpickr library is only for dates and times. You cannot do that with this library. Elementor cannot do that either. You need to add the pattern attribute to the element using JS. Paste this code in a Custom HTML widget AFTER the form that has the tel input and replace FIELD_ID with the id of your tel input field.

<script>
const tel = document.querySelector('#form-field-FIELD_ID')

tel.setAttribute('pattern', '[0-9]*\d{8,8}')
</script>

@Oaufi
Copy link

Oaufi commented Aug 19, 2022

Any idea how to html for Elementor for tel filed to accept only numbers and 8 digit?

The Flatpickr library is only for dates and times. You cannot do that with this library. Elementor cannot do that either. You need to add the pattern attribute to the element using JS. Paste this code in a Custom HTML widget AFTER the form that has the tel input and replace FIELD_ID with the id of your tel input field.

<script>
const tel = document.querySelector('#form-field-FIELD_ID')

tel.setAttribute('pattern', '[0-9]*\d{8,8}')
</script>

Thanks, I should try that magic and update you. Appreciated your fully support.

@doggopress
Copy link

@ashkan-ahmadi Can you help me to make the minimum date on this form to be 5 days from today? I cannot get it to work: https://bunsbakery.co.za/custom-order/

@ashkan-ahmadi
Copy link

@doggopress Yeah that's easy. You need to set minDate to new Date().fp_incr(5) so the minimum date is always 5 days from today. Let me know how that goes

@doggopress
Copy link

@doggopress Yeah that's easy. You need to set minDate to new Date().fp_incr(5) so the minimum date is always 5 days from today. Let me know how that goes

Thank you @ashkan-ahmadi it worked for me!

Now my only problem is that it does not work on mobile. Can you assist with this?

@naayaab
Copy link

naayaab commented Apr 27, 2023

i myself think the best way to do is to use this simple JS to achieve min or max date,

first use either elementor pro's custom code feature or a plugin like header footer script and past this code
for min date to current
<script> var form = document.querySelector('#form-field-FIELD_ID'); var currentDate = new Date().toJSON().slice(0, 10); form.setAttribute('min', currentDate); </script>
chnage field id to your specific field id

@mrpap
Copy link

mrpap commented Jun 2, 2023

Elementor gives the option to select "Native HTML5" for the datepicker (same for time picker btw.)
If you select Native HTML5, then you can pass the attributes "min" and "max" without a lot of effort.

In my case, I would like the datepicker to have a minimum date of today.
The ID of the field is defined as "MyID" but to actually identify it, I had to use "form-field-MyID".

Right after the form you have created, add a HTML widget and pass following code to it:

<script>
var today= new Date().toLocaleDateString();
document.getElementById("form-field-MyID").setAttribute("min", today);
</script>

I hope this helps. You should also have some server-side validation as mentioned in previous comments.

@Ozman-Minhas
Copy link

Ozman-Minhas commented Jul 3, 2023

Forgive me for being obtuse. I am using Elementor Pro (precisely because I am not a backend developer. So all this code-speak is confusing without hand holding for this noob.)

Would you kindly explain for me what parts of the above JavaScript can be used in the Elementor Page itself using the HTML widget?

And, which part I must use with a Header/Footer code-injection plugin.

**How would you write the code to reflect this scenario: (and precisely, where does each part go)

Form Element Date picker 1. User puts in Start Date (field ID-'start_date') which can be today or any day in the future

Form Element Date Picker 2. User puts in End Date (field ID-'end_date') which CANNOT EXCEED +20 DAYS from 'start_date'.**

This is used in a Guest Pass form where it will be issued up to no more than 21 days total. Even though it says "Maximum 21 Days", people still put in whatever dates they want and I have to manually correct the submission...grrrr.

((The thing I don't understand with the Elementor Date Picker widget is why would you have a min/max date that you have to pick on the calendar instead of this +/- date parameter so it can be evergreen, like what I am looking for.))

Thank you in advance for your help!

guest-pass-form

<script>
window.addEventListener('DOMContentLoaded', () => {
   setTimeout(() => {
       flatpickr("#form-field-YOUR-FIELD-ID", {
    mode: "range",
    altInput: true,
    altFormat: "F j, Y",
    dateFormat: "Y-m-d",
    minDate: new Date().fp_incr(1),
    maxDate: new Date().fp_incr(21)
       });
   }, 500) 
});
</script>

Instructions:
1- Drage and drop the HTML widget on the page (preferably at the bottom of the page) where you have this form and copy and paste the above-mentioned code.
2- Change YOUR-FIELD-ID with the ID of date field in your form.
3- If you want to change the date range, change the numbers in the following code:

  
    minDate: new Date().fp_incr(1),
    maxDate: new Date().fp_incr(21)
    
    Remember: You can get more examples here: https://flatpickr.js.org/examples/

Hope it helps.

@oscarhenao
Copy link

Looking forward to have this implemented without the need of coding very soon in Elementor. Thank you @Ozman-Minhas for the solution provided

@dasigna
Copy link

dasigna commented Nov 24, 2023

<script>
window.addEventListener('DOMContentLoaded', () => {
   setTimeout(() => {
       flatpickr("#form-field-YOUR-FIELD-ID", {
    mode: "range",
    altInput: true,
    altFormat: "F j, Y",
    dateFormat: "Y-m-d",
    minDate: new Date().fp_incr(1),
    maxDate: new Date().fp_incr(21)
       });
   }, 500) 
});
</script>

Instructions: 1- Drage and drop the HTML widget on the page (preferably at the bottom of the page) where you have this form and copy and paste the above-mentioned code. 2- Change YOUR-FIELD-ID with the ID of date field in your form. 3- If you want to change the date range, change the numbers in the following code:

  
    minDate: new Date().fp_incr(1),
    maxDate: new Date().fp_incr(21)
    
    Remember: You can get more examples here: https://flatpickr.js.org/examples/

Hope it helps.

nice finding, thanks @Ozman-Minhas .
nevertheless i discovered a little glitch when fiddling around actually...

using in html code widget beneath the form:

<script>
window.addEventListener('DOMContentLoaded', () => {
   setTimeout(() => {
       flatpickr("#form-field-XXX", {
    altFormat: "l, d. F Y",
    dateFormat: "l, d. F Y",
    minDate: new Date().fp_incr(1),
    maxDate: new Date().fp_incr(100),
    "disable": [
        function(date) {
            // return true to disable
            return (date.getDay() === 1 || date.getDay() === 2);
        }],
    locale: {
        firstDayOfWeek: 1 // start week on Monday
	}
       });
   }, 500) 
});
</script>

outputs the desired result and works... BUT: unfortunately changes the default language from german back into english!
this means that the datepicker as well as the date output suddenly reverses back from de to en.

anybody any clue why?

@oscarhenao
Copy link

oscarhenao commented Nov 25, 2023 via email

@dasigna
Copy link

dasigna commented Nov 27, 2023

@oscarhenao - thanks, the localisation options are known - but:

first thing: the form as well as the flatpickr UI etc. is in the right language (german) natively. injecting this script changes everything to english including the field output.
that is happening without changing anything through the injected script... a result that exceeds my knowledge.

second: already had the idea to tweak something within the script to revert the language back to german - but cant get it to work in no way... sadly.

had a few hopes someone here has more knowledge about this thing and might help out or might be able to explain whats happening here.

so basically:
why does the script change the language?
and how to avoid this to happen??

sincere greetings.

@rizbaig
Copy link

rizbaig commented Dec 14, 2023

Hi there!
I have an elementor form with time field, I have to make range selection between 10am to 4pm only for clients, can anyone help me to do so?
Thanks

@oscarhenao
Copy link

oscarhenao commented Dec 14, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/developer-api Indicates when a topic is related to the Developer API and Documentation. widget/forms References the Form (Pro) widget and its features.
Projects
None yet
Development

No branches or pull requests