Client Script: On Change | multiple conditions

Spaceballs
Kilo Sage

Hi,

I created a script in the Client Script but I have multiple conditions that I need to create and it is not working.

 

 

Capture2.PNG

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
    if (isLoading || newValue === '') {
        g_form.clearValue('milestone');
        return;
    }
    var addDays;
    if (g_form.getValue('priority') == "A") {
        //add days
        addDays = "56";
    }
    //get kickoff date value
    var startDate = new Date(g_form.getValue('kickoff_date'));

    var addDaysToSartDate = "";

    //get kickoff date
    var getDateFromStartDate = startDate.getDate();

    //subtract 56 days from the kickoff selected date
    var totalDays = parseInt(getDateFromStartDate) - parseInt(addDays);

    startDate.setDate(totalDays);

    //g_user_date_format representing the user's date preferred date format which is yyyy-MM-dd
    addDaysToSartDate = formatDate(startDate, g_user_date_format);

    //Retrieves a field value from the form NOT the database
    g_form.setValue('milestone', addDaysToSartDate);
}

Result

Capture.PNG

 

How can I revise the code and add multiple ifs condition

 

If Priority == A then adddays -56

else if Priority == B then adddays -6

else if Priority == C then adddays -2

else if Priority == D then adddays -10

 

Output should be in date format and should be populate in the milestone field.

 

Thanks for your help

1 ACCEPTED SOLUTION

I followed your scripts

Actually you didn't and made a couple of fundamental mistakes because of which the GlideAjax handler Script Include will not work 😀:

- you added an initialize method to the Script Include - should not be done (it can ba done, but that's a topic for another day) and the Script Include provided does not contain one:

var communityDates = Class.create();
communityDates.prototype = {
	// this method must not exist
	initialize: function () {},
	...

- the class does not extend AbstractAjaxProcessor; proposed code:

var communityDates = Class.create();
communityDates.prototype = Object.extendsObject(AbstractAjaxProcessor, {
...

your code:

var communityDates = Class.create();
communityDates.prototype = {
...

But given that your are working in scope, the proposed code is also not OK; it should be:

var communityDates = Class.create();
communityDates.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
...

notice the extra global. scope name in front of AbstractAjaxProcessor.

Now this is not an error, but in the Client Script one can forego

var answer = trigger.responseXML.documentElement.getAttribute('answer');

in

function getDatedata (trigger) {
	var answer = trigger.responseXML.documentElement.getAttribute('answer');
	...

if, when calling the GlideAjax handler, instead of

gar.getXML(getDatedata);

one writes

gar.getXMLAnswer(getDatedata);​

in that case the parameter of function getDatedata alreade is "answer":

function getDatedata (answer) {
	...

Than another big problem is trying to crate a GlideDateTime directly from the date value arriving from the client side through parameters. GlideDateTime can only correctly decode format YYYY-MM-DD HH:mm:ss - which is the internal Date/time format. It also expects that value to be in UTC TZ, which for +95% of user on the planet will not be the case. In other cases the system will try to guess the format used, but half the time a date where the day is 12 or less than that - e.g. 3/2/2023 - will not be correctly decoded.

The solution to correctly getting the value of a Date or Date/time field client side is to use a function provided by ServiceNow (getDateFromFormat) and one of two variables also provided by ServiceNow (g_user_date_format and g_user_date_time_format). In your case:

var kickoffDateValue = getDateFromFormat(g_form.getValue('kickoff_date'), g_user_date_format);

This will place the date value as a Unix epoch millisecond into variable kickoffDateValue. This can be used both to correctly initialize a Date object client side or a GlideDate or a GlideDateTime server side.

 

So in the onChange client script you could write:

var kickoffDateValue = new Date(getDateFromFormat(g_form.getValue('kickoff_date'), g_user_date_format));

Thus you don't need a GlideAjax call or Script Include; the client side code could be something like:

function onChange (control, oldValue, newValue, isLoading, isTemplate) {
	if (isLoading || newValue === '') {
		return;
	}

	var priorityOffsetDB = {
		'A': -56,
		'B': -6,
		'C': -2,
		'D': -10,
	};

	var kickoffDate = new Date(getDateFromFormat(g_form.getValue('kickoff_date'), g_user_date_format));
	var priority = g_form.getValue('priority');

	if (typeof priorityOffsetDB[priority] != 'undefined') {
		kickoffDate.setDate(kickoffDate.getDate() + priorityOffsetDB[priority]);
		g_form.setValue('milestone', formatDate(kickoffDate, g_user_date_time_format));
	}
}

 

View solution in original post

20 REPLIES 20

Except you are working in global scope whereas the OP is working in a private scope. So your solution will not work as pasted above (missing global scope qualifier for AbstractAjaxProcessor).

@BharathChintala - thank you so much for your response and help. Unfortunately, I was not able to get the script to work 😞 

I followed your scripts

Actually you didn't and made a couple of fundamental mistakes because of which the GlideAjax handler Script Include will not work 😀:

- you added an initialize method to the Script Include - should not be done (it can ba done, but that's a topic for another day) and the Script Include provided does not contain one:

var communityDates = Class.create();
communityDates.prototype = {
	// this method must not exist
	initialize: function () {},
	...

- the class does not extend AbstractAjaxProcessor; proposed code:

var communityDates = Class.create();
communityDates.prototype = Object.extendsObject(AbstractAjaxProcessor, {
...

your code:

var communityDates = Class.create();
communityDates.prototype = {
...

But given that your are working in scope, the proposed code is also not OK; it should be:

var communityDates = Class.create();
communityDates.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
...

notice the extra global. scope name in front of AbstractAjaxProcessor.

Now this is not an error, but in the Client Script one can forego

var answer = trigger.responseXML.documentElement.getAttribute('answer');

in

function getDatedata (trigger) {
	var answer = trigger.responseXML.documentElement.getAttribute('answer');
	...

if, when calling the GlideAjax handler, instead of

gar.getXML(getDatedata);

one writes

gar.getXMLAnswer(getDatedata);​

in that case the parameter of function getDatedata alreade is "answer":

function getDatedata (answer) {
	...

Than another big problem is trying to crate a GlideDateTime directly from the date value arriving from the client side through parameters. GlideDateTime can only correctly decode format YYYY-MM-DD HH:mm:ss - which is the internal Date/time format. It also expects that value to be in UTC TZ, which for +95% of user on the planet will not be the case. In other cases the system will try to guess the format used, but half the time a date where the day is 12 or less than that - e.g. 3/2/2023 - will not be correctly decoded.

The solution to correctly getting the value of a Date or Date/time field client side is to use a function provided by ServiceNow (getDateFromFormat) and one of two variables also provided by ServiceNow (g_user_date_format and g_user_date_time_format). In your case:

var kickoffDateValue = getDateFromFormat(g_form.getValue('kickoff_date'), g_user_date_format);

This will place the date value as a Unix epoch millisecond into variable kickoffDateValue. This can be used both to correctly initialize a Date object client side or a GlideDate or a GlideDateTime server side.

 

So in the onChange client script you could write:

var kickoffDateValue = new Date(getDateFromFormat(g_form.getValue('kickoff_date'), g_user_date_format));

Thus you don't need a GlideAjax call or Script Include; the client side code could be something like:

function onChange (control, oldValue, newValue, isLoading, isTemplate) {
	if (isLoading || newValue === '') {
		return;
	}

	var priorityOffsetDB = {
		'A': -56,
		'B': -6,
		'C': -2,
		'D': -10,
	};

	var kickoffDate = new Date(getDateFromFormat(g_form.getValue('kickoff_date'), g_user_date_format));
	var priority = g_form.getValue('priority');

	if (typeof priorityOffsetDB[priority] != 'undefined') {
		kickoffDate.setDate(kickoffDate.getDate() + priorityOffsetDB[priority]);
		g_form.setValue('milestone', formatDate(kickoffDate, g_user_date_time_format));
	}
}

 

Thank you @-O- , your simple script works flawlessly 🙂 and thank you for educating me

You're most welcome.

Though I must say the above solution can be improved upon:

- create a custom table extending sys_choice that has an extra field: Days offset (because such a table would extend sys_choice, there will be no custom table license costs associated with it).

- create a display business rule that places the Choice and Days offset on the scratchpad.

- modify the script to use the days offset database on the scratchpad, placed there by the display business rule.

The advantage is that once the Solution is in place, the data can be modified to suite any need, without touching the code again - a major principle of programming will have been followed: separation of data and code.