Need to verify Implement on Change Request is inside planned window

Aaron Duncan
Mega Sage

I have a requirement that when a user clicks the OOB 'Implement' button on the Change Request, it will validate that the click is after the Planned Start field, and if not, popup a window with a simple dropdown that they must select a reson it is going early. 

 

In my current code, I am calling a client callable Script Include that will check between the click date/time and the Planned start date time.

Here is the UI Action.

Client - Checked

Code:

//Client-side 'onclick' function
function moveToImplement() {
    var startDate = g_form.getValue('start_date');
    var isItPassed = new DateUtil().hasDatePassed(startDate);
    if (isItPassed == true) {
		//if the time is passed, then continue as normal.
        g_form.setValue("state", "-1");
        gsftSubmit(null, g_form.getFormElement(), "state_model_move_to_implement");
    } else {
		//If the click happens before the Planned Start DateTime, then create the popup requiring a reason through a UI Page.
        var tableName = g_form.getTableName();
        var dialog = new GlideDialogWindow('change_start_early');
        dialog.setTitle("Reason why Change is going early.");
        dialog.setPreference("target_table", tableName);
        dialog.render();
    }
}
//Call the UI Action and skip the 'onlick' function
gsftSubmit(null, g_form.getFormElement(), 'state_model_move_to_implement');
if (typeof window == 'undefined')
       setRedirect();

    function setRedirect() {
        current.update();
        action.setRedirectURL(current);
    }

 

Here is the Script Include.

Client Callable - checked 

Accessible from This application scope only (global)

 

var DateUtil = Class.create();
DateUtil.prototype = Object.extendsObject(AbstractAjaxProcessor,{
    initialize: function() {},
    // Usage: new DateUtil().hasDatePassed(current.getValue('state_date'))
    //
    hasDatePassed: function(dateFieldValue) {
        var now = new GlideDateTime();
        var startDt = new GlideDateTime(dateFieldValue);

        if (startDt.getNumericValue() < now.getNumericValue())
            return true;

        return false;

    },
    type: 'DateUtil'
});

 

I get the error:

2023-11-30_10-27-30.png

In the UI, nothing appears to change.

1 ACCEPTED SOLUTION

Aaron Duncan
Mega Sage

I was able to figure this out, as I updated the Script Include to this:

 

var DateUtil = Class.create();
DateUtil.prototype = Object.extendsObject(AbstractAjaxProcessor, {
  // Usage: new DateUtil().hasDatePassed(current.getValue('state_date'))
  // Based of of a script in the Community provided by Chuck Tomasi
  hasDatePassed: function () {
    var dateFieldValue = this.getParameter("sysparm_startDate");
    var now = new GlideDateTime();
    var startDt = new GlideDateTime(dateFieldValue);

    if (startDt.getNumericValue() < now.getNumericValue()) {
      return true;
    } else {
      return false;
    }
  },
  type: "DateUtil",
});

 and the UI Action updated to now call the GlideAjax call to compare the time values, and create a popup if required.

 

function moveToImplement() {
  // Create AJAX call to determine if start date value is smaller than now. If it is, then proceed. Otherwise, create popup.
  var startDate = g_form.getValue("start_date");
  var ga = new GlideAjax("DateUtil"); // Script Include to call.
  ga.addParam("sysparm_name", "hasDatePassed"); //Function in the Script Include to call.
  ga.addParam("sysparm_startDate", startDate); //passing the startDate into the function.
  ga.getXMLAnswer(_isItPassed); //Callback function to return the result when ready.

  //Call the UI Action and skip the 'onlick' function
  // gsftSubmit(null, g_form.getFormElement(), "state_model_move_to_implement");
  // if (typeof window == "undefined") setRedirect();

  // function setRedirect() {
  //     current.update();
  //     action.setRedirectURL(current);
  // }

  function _isItPassed(response) {
    var answer = response;
    if (answer === "true") {
      //if the answer is true, the start date/time is passed and can move to implement.
      g_form.setValue("state", "-1");
      gsftSubmit(
        null,
        g_form.getFormElement(),
        "state_model_move_to_implement"
      );
      // if (typeof window == "undefined") setRedirect();
      current.update();
      action.setRedirectURL(current);
    } else {
      renderForm(); //If false, then it creates the popup. once the popup is complete, then it will move along in the process.
    }
  }

  function renderForm() {
    var tableName = g_form.getTableName();
    var dialog = new GlideDialogWindow("change_start_early");
    dialog.setTitle("Reason why Change is going early.");
    dialog.setPreference("target_table", tableName);
    dialog.render();
  }
}

View solution in original post

5 REPLIES 5

Tony Chatfield1
Kilo Patron

Hi, in your client script you appear to be instantiating the Ajax call as you would a normal script-include function.

var isItPassed = new DateUtil().hasDatePassed(startDate);

This is not the correct syntax for Ajax, where you need to pass in the function and any other inputs via addParam() 

You server-side script also needs to use this.getParameter() to retrieve and consume the parameters that the client script passes in.

Your script-include will the return a result to the client and this result will need to be parsed before it can be used,

The examples in the doc's are the format\syntax that you need to follow.
GlideAjax | ServiceNow Developers

I updated the UI Action to call the Script Include through GlideAjax, but it's not returning anything.

 

The updated call.

  var startDate = g_form.getValue('start_date');
	var ga = new GlideAjax('DateUtil'); // Script Include to call.
	ga.addParam('sysparm_name','hasDatePassed'); //Function in the Script Include to call.
	ga.addParam('sysparm_startDate',startDate); //passing the startDate into the function.
	ga.getXMLAnswer(isItPassed, null, answer); //Callback function to return the result when ready.
	var answer;

 

the function to process the reponse. I updated the logic to look at the answer variable instead. when I output the variable and the response, they're both null.

function isItPassed(response){
	answer = response;
}

 

Here's the Script Include

 

var DateUtil = Class.create();
DateUtil.prototype = Object.extendsObject(AbstractAjaxProcessor,{
    initialize: function() {},
    // Usage: new DateUtil().hasDatePassed(current.getValue('state_date'))
    //
    hasDatePassed: function(dateFieldValue) {
        var now = new GlideDateTime();
        // var startDt = new GlideDateTime(dateFieldValue);
		var startDt = this.getParameter("sysparm_startDate");

        if (startDt.getNumericValue() < now.getNumericValue()) {
			response = true;
            return JSON.stringify(response);
	} else {
		response = false;
        return JSON.stringify(response);

    }},
    type: 'DateUtil'
});

Hi, I think you would need to instantiate your dateTime field as a  GlideDataeTime object, so that you can make the numericValue comparison. Untested by something like this

hasDatePassed: function() {
   var dateFieldValue = this.getParameter("sysparm_startDate");
   var now = new GlideDateTime();
   var startDt = new GlideDateTime(dateFieldValue);

 

I've done so, and to validate the Script Include, I tested using a background script. The logic and everything works as expected there. It's just not passing anything back to the callback function. No matter what, it comes back as undefined. It's as though it's not passing back any data from the Script Include, or the function itself isn't seeing the response.

//Callback function - using xmlAnswer as the value returned by the function now.
function isItPassed(xmlAnswer){
	if(xmlAnswer == 'true') {
		g_form.addInfoMessage('The answer is true'); //Used to test what value is being sent
		return true;
	} else if (xmlAnswer == 'false') {
		g_form.addInfoMessage('Answer is false.'); //Used to test what value is being sent
		return false;
	} else {
		g_form.addInfoMessage('3rd answer: ' + xmlAnswer); //Used to test what value is being sent - This keeps showing null, but the alert shows undefined.
		return false;
	}
}