Prevent Submission of Catalog Item With a Date in the Past

jmiskey
Kilo Sage

We have many Catalog Items that have a date field like "Effective Date", where the date entered cannot be in the past.  We have always handled it with a On Change Catalog Client Script, right on that date Variable, to do a GlideAjax call to a bunch of date functions to check/verify the date is not in the past, and this has always worked well.

 

However, with the most recent versions of ServiceNow, it now has/allows a "Save as Draft" option for Catalog Items.  So now people could enter an Effective Date of today, and then save the Catalog Item as a draft.  They could then re-open that draft tomorrow and submit it.  We do not want to allow that to happen, as tomorrow, the date they entered in the Effective Date field will be in the past, and therefore should not be allowed.  So I think we need to add similar logic that we have in the On Change Catalog Client Script to an On Submit Catalog Client Script.

 

When I tried doing that, it did not work.  It ran, but did not prevent the record from being submitted like it should.  From research, it appears that you cannot use GlideAjax calls in On Submit Catalog Client Scripts.  So what is the best way of handling this?

 

Here is the I attempted, which uses the same logic/GlideAjax call as my On Change Script:

function onSubmit() {
   //Needed due to the ability to "Save as Draft"

	var dndt = g_form.getValue('effective_date'); //First Date/Time field  
    var dttype = 'day'; //this can be day, hour, minute, second. By default it will return seconds.  

    var ajax = new GlideAjax('global.ClientDateTimeUtils');  
    ajax.addParam('sysparm_name','getNowDateTimeDiff');  
    ajax.addParam('sysparm_fdt', dndt);  
    ajax.addParam('sysparm_difftype', dttype);  
    ajax.getXML(doSomething);  

    function doSomething(response){  
        var answer = response.responseXML.documentElement.getAttribute("answer");  
        //check to see if request for old date (by seeing if difference between now and request date < -1)  
        alert(answer);
        if (answer<=-1) {
            alert("Effective Date cannot be a date in the past!");
            g_form.setValue('effective_date','');
			return false;  //disable submission
        }else{
			return true;
		}
    }  
   
}

Thanks

1 ACCEPTED SOLUTION

Zach Koch
Giga Sage
Giga Sage

Unless you need more data from the server, you can actually just prevent past dates through UI policy where it will clear out the value if it is in the past, which will prevent people from being able to save a draft like you mentioned, with the date in the past. Take a look at this post.

No Code date validations through (Catalog) UI Policies 

If this information helped resolve your issue, please remember to mark response correct and thumbs up to help future community members on this information, thanks!

View solution in original post

18 REPLIES 18

Moin Kazi
Kilo Sage
Kilo Sage

Hi @jmiskey ,

 

The only way to use GlideAjax in an onSubmit client script is to use getXMLWait and make a synchronous call to the server. but getXMLWait won't work on service portal.

Or

Another way is you can delay your submission until GlideAjax is complete. See below script which can help you to do Glide AJAX Call on onSubmit script.

 

function onSubmit() {
	if (!g_form.ajaxComplete) {
		ajaxCall();
		return false;
	}
}

function ajaxCall() {
	var ga = new GlideAjax(script_include);
	ga.addParam("sysparm_name", function_name);
	getXMLAnswer(function(a){
		// Do whatever you want to with the answer
		// Once you've handle the answer, run these two lines:
		g_form.ajaxComplete = true;
		g_form.submit();
	});

 

I hope this helps you.

 

Regards

Moin

Is there a way to do this without using GlideAjax?  Is it even necessary at all?

 

I am not sure how to adapt my code into the format you have shown.

Hi @jmiskey 

 

See Below Code you can compare date and return false if its enter in If loop -

 

 

function onSubmit() {

const now = new Date();

    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are zero-indexed
    const day = String(now.getDate()).padStart(2, '0');
    const hours = String(now.getHours()).padStart(2, '0');
    const minutes = String(now.getMinutes()).padStart(2, '0');
    const seconds = String(now.getSeconds()).padStart(2, '0');
 
   //this is the format which i have convert date to compare - 2019-07-23 02:34:57

    var currentDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; 

    if (currentDate > g_form.getValue('opened_at')) {
        alert("date in past");
        return false;
    }
}
 
You can replace g_form.getValue('opened_at') with your date field which you want to compare
 
I hope it help you
 
Regards
Moin

That code does not appear to be working.  Firstly, it does not appear that "const" is valid to use in Client Scripts.  I changed then all to "var".  But the issue is that this returns a time piece for comparison.  We need to really to do is remove the time pieces from all dates for the sake of comparison.

 

I am having the same issue with the Effective Date field.  Even though we are using a Date field, it still seems to capture the time.  I tried using various methods to remove the hours, but then it returns odd dates, because of the GMT time difference.

 

So if I created a new date in my script, and tried to remove the hours, it was returning the wrong date.  For example, if I tried to create todays date, 2024-10-09 00:00:00, when I tried to do date math on it, it was changing it to 2024-10-08 20:00:00 (because we are GTM - 4:00).  So if you try to remove the hours, it would return 2024-10-08, which is the wrong date (it should be 2024-10-09).

 

Working with dates in ServiceNow is such a pain!  It shouldn't be this difficult!

I am thinking of coming at this from a different angle and asking this question in a very different way.  

jmiskey
Kilo Sage

OK, I think I found an article that ALMOST does what I need in a simple manner (this here: https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0820044).  The only issue is that is does not allow me to submit the current date (which it should allow).  It doesn't matter if I change "<=" to "<".  I think it is because it may be returning a time component when it is creating the "current_date" variable.  How can I create that variable without a time component (or using midnight)?

 

I tried this update to the code, which should remove all time pieces from both dates, and it still is not working when I choose the current date.

 

function onSubmit() {
   //Needed due to the ability to "Save as Draft"

	var eff_date = new Date(g_form.getValue('effective_date'));
	eff_date.setHours(0,0,0,0);  //set hours of date to zero
	var current_date = new Date();
	current_date.setHours(0,0,0,0);  //set hours of date to zero
	if (eff_date < current_date) {
		alert("Effective Date cannot be a date in the past!");
		g_form.setValue('effective_date','');
		return false;
	}
   
}

 

Since the dates should be the same value, they should be equal, and my inequality check should fail, meaning it should not return the message and should not cancel the submission.  But it does...