I want to return Array from script include and use it in the glide ajax of client script what's wrong in my approach...

Aditya Kumar
Kilo Guru

client script

    var ga = new GlideAjax('TASK_return_array_SI');
    ga.addParam('sysparm_name', 'getCallerDetails');
    ga.addParam('sysparm_inc', g_form.getValue('caller_id'));
    ga.getXML(showDetails);

    function showDetails(response) {
        var answer = response.responseXML.documentElement.getAttribute("answer");
        for (a = 0; a < answer.length; a++); {
           g_form.setValue('description',a);
        }
    }

script include

	getCallerDetails: function() {
        var caller_sysID = this.getParameter('sysparm_inc');
        var incidentGR = new GlideRecord('sys_user');
        incidentGR.addquery('sys_id', caller_sysID);
        incidentGR.query();
		var array = [];
        if (incidentGR.next()) {
			array.push(incidentGR.name.toString());
			array.push(incidentGR.email.toString());
        }
        return array;
    },
	
1 ACCEPTED SOLUTION

Hitoshi Ozawa
Giga Sage
Giga Sage

Hi again,

This will probably be a repeat of what others have already replied. Added further information on why the original script is not working.

Since ServiceNow is only capable of returning a string, it's is now necessary to convert object to string in Script Include so the original script will become like below as others have already replied.

var TASK_return_array_SI = Class.create();
TASK_return_array_SI.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    getCallerDetails: function() {
        var caller_sysID = this.getParameter('sysparm_inc');
        var incidentGR = new GlideRecord('sys_user');
        incidentGR.addquery('sys_id', caller_sysID);
        incidentGR.query();
        var array = [];
        if (incidentGR.next()) {
            array.push(incidentGR.name.toString());
            array.push(incidentGR.email.toString());
        }
        return JSON.stringify(array); // convert array to string
    },
    type: 'TASK_return_array_SI'
});

Since there is no longer any benefit of using getXML over getXMLAnswer, I've converted to use getXMLAnswer to avoid xml parsing.

I'm parsing the returned string to get an object back using JSON.parse.

In the original code in the question, there is a semi-colon ";" in the for loop. This will end the for loop with this 1 statement instead of processing the intended g_form.setValue() statement. The value of variable "a" will also become 2 because the loop has ended. Since there is no element a[2], the value of field "description" will become "undefined".

for (a = 0; a < answer.length; a++); {

I've removed this semi-colon to loop. The setValue, however, will over-write the previously set value so the displayed value will be email address only.

function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') {
        return;
    }
    var ga = new GlideAjax('TASK_return_array_SI');
    ga.addParam('sysparm_name', 'getCallerDetails');
    ga.addParam('sysparm_inc', g_form.getValue('caller_id'));
    ga.getXMLAnswer(showDetails);

    function showDetails(answer) {
        //var answer = response.responseXML.documentElement.getAttribute("answer");
        answer = JSON.parse(answer); // parse answer
        for (var a = 0; a < answer.length; a++) { // remove ";"
            g_form.setValue('description', answer[a]);
        }
        //g_form.setValue('description', answer.join(', '));  // to display both name and email
    }
}

Execution result

 

View solution in original post

18 REPLIES 18

John Dahl
Tera Guru

You cannot transmit complex objects from the server to the client. Whichever structure you prefer (array, object, etc.), if the value type is not a string, then you need to stringify the object before you can send it to the client, then parse it on the client.

 

Given an array or object in the script include (server-side):

return JSON.stringify( answer );

Given a GlideAjax call with a callback function in the client script:

var ga = new GlideAjax(....

...

ga.getXMLAnswer( callback );

function callback( answer ){

  answer = JSON.parse( answer );

  // Do something with the answer

}

 

Hitoshi Ozawa
Giga Sage
Giga Sage

Hi Aditya,

getXML() used to convert the object to a xml and then send it over to client but it now looks like it's sending everything over as a string. In I the following from Script Include, I'll get a returned type as an "string" with the value of "[object Object]" in client console.

Script Include

return {"test": "testValue"};

Client Script

console.log(typeof answer);
console.log("answer: %o", answer);

Result

string
answer:  [object Object]

 

To see the content of the reply, I've added the following in Client Script.

console.log("response: %s", response.responseText);

In the console, following was displayed. So the value of "answer" is a string "[object Object]".

response: <?xml version="1.0" encoding="UTF-8"?><xml answer="[object Object]" sysparm_max="15" sysparm_name="getCallerDetails" sysparm_processor="TASK_return_array_SI"/>

 

Furthermore, the documentation on getXMLAnswer seems to be wrong. getXMLAnswer is also returning result as a string and not in XML format.

getXMLAnswer(Function callback, Object additionalParam, Object responseParam)

Calls the processor asynchronously and gets the answer element of the response in XML format.
 

Hitoshi Ozawa
Giga Sage
Giga Sage

Hi again,

This will probably be a repeat of what others have already replied. Added further information on why the original script is not working.

Since ServiceNow is only capable of returning a string, it's is now necessary to convert object to string in Script Include so the original script will become like below as others have already replied.

var TASK_return_array_SI = Class.create();
TASK_return_array_SI.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    getCallerDetails: function() {
        var caller_sysID = this.getParameter('sysparm_inc');
        var incidentGR = new GlideRecord('sys_user');
        incidentGR.addquery('sys_id', caller_sysID);
        incidentGR.query();
        var array = [];
        if (incidentGR.next()) {
            array.push(incidentGR.name.toString());
            array.push(incidentGR.email.toString());
        }
        return JSON.stringify(array); // convert array to string
    },
    type: 'TASK_return_array_SI'
});

Since there is no longer any benefit of using getXML over getXMLAnswer, I've converted to use getXMLAnswer to avoid xml parsing.

I'm parsing the returned string to get an object back using JSON.parse.

In the original code in the question, there is a semi-colon ";" in the for loop. This will end the for loop with this 1 statement instead of processing the intended g_form.setValue() statement. The value of variable "a" will also become 2 because the loop has ended. Since there is no element a[2], the value of field "description" will become "undefined".

for (a = 0; a < answer.length; a++); {

I've removed this semi-colon to loop. The setValue, however, will over-write the previously set value so the displayed value will be email address only.

function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') {
        return;
    }
    var ga = new GlideAjax('TASK_return_array_SI');
    ga.addParam('sysparm_name', 'getCallerDetails');
    ga.addParam('sysparm_inc', g_form.getValue('caller_id'));
    ga.getXMLAnswer(showDetails);

    function showDetails(answer) {
        //var answer = response.responseXML.documentElement.getAttribute("answer");
        answer = JSON.parse(answer); // parse answer
        for (var a = 0; a < answer.length; a++) { // remove ";"
            g_form.setValue('description', answer[a]);
        }
        //g_form.setValue('description', answer.join(', '));  // to display both name and email
    }
}

Execution result

 

buddy it worked but its not showing the 'name' only showing the 'email' and email is always survey.user@email.com

Change as follows.

    function showDetails(answer) {
        answer = JSON.parse(answer); // parse answer
		g_form.setValue('description', answer);
    }

Execution result

find_real_file.png