Passing an Array of objects via glideAjax

Community Alums
Not applicable

Afternoon All,

So I've been working on a script where I am testing to see if an incidents caller has access to any of the attached KBs using GlideAjax. I want to then pass that list of KBs (as objects containing, number, short_desc and sys_id) back to the client script but am having a hard time outputting the results on the client side.

Could someone look it over for me and see what I'm doing wrong:

ServerSide Script:

var kbResolveCriteriaCheck = Class.create();
kbResolveCriteriaCheck.prototype = Object.extendsObject(AbstractAjaxProcessor, {
	
	verifyAccess: function(){
		//defines base variables
		var logText = '';
		var caller = this.getParameter('sysparm_caller');
		var inc_num = this.getParameter('sysparm_inc_num');
		var kbArticle = '';
		var kbBase = '';
		var canReadKBBase = '';
		var kbList = [];
		
		//gets the incidents sys_id
		var inc_sys_id = new GlideRecord('incident');
		inc_sys_id.get('number',inc_num);
		inc_sys_id = inc_sys_id.sys_id;
		
		logText = 'Caller: ' + caller + '\n';
		logText += 'Incident Number: ' + inc_num + '\n';
		logText += 'Incident SYS_ID: ' + inc_sys_id + '\n';
		
		//gets the users list of criteria groups
		var callersCriteria = SNC.UserCriteriaLoader.getAllUserCriteria(caller).toString();
		//callersCriteria = callersCriteria.split(',');
		logText += 'User Criteria groups: ' + callersCriteria.toString() + '\n';
		
		//Gets the Last KB and the associated KB Base for the last KBA attached to the incident
		var getKB = new GlideRecord('m2m_kb_task');
		getKB.addQuery('task',inc_sys_id);
		getKB.orderByDesc('sys_created_on');
		//getKB.setLimit(1);
		getKB.query();
		//if no KB's returned none were attached
		if (!getKB.hasNext()) {
			logText += 'No KB Attached \n';
			gs.log(logText,'kbResolveCriteriaCheck');
			return 'No Attached KB';
		}
		while (getKB.next()) {
			kbArticle = getKB.kb_knowledge;
			kbBase = getKB.kb_knowledge.kb_knowledge_base;
			logText += 'KBArticle: ' + kbArticle + '\n';
			logText += 'kbBase: ' + kbBase + '\n';
			//lookups the KB Base to see if the user has access to it
			var getKBCriteria = new GlideRecord('kb_uc_can_read_mtom');
			getKBCriteria.addQuery('kb_knowledge_base',kbBase);
			getKBCriteria.addQuery('user_criteria','IN',callersCriteria);
			getKBCriteria.query();
			if (getKBCriteria.next()) {
				canReadKBBase = 'true';
				logText += 'User can read KB Base\n';
			}
			//user does not have access to KBbase so break
			else if (!getKB.hasNext()){
				break;
			}
			
			//get's the articles roles
			if (canReadKBBase == 'true') {
				var kbRoles = kbArticle.roles;
				logText += 'KBA Roles: ' + kbRoles + '\n';
				//looks to see if the end user has that role or if the role is empty;
				if (gs.getUser().getUserByID(caller).hasRole(kbRoles) || JSUtil.nil(kbRoles)) {
					//if has roles or role is empty builds the link
					var obj = {};
						obj.number = kbArticle.number;
						obj.short_desc = kbArticle.short_description;
						obj.sys_id = kbArticle.sys_id;
						kbList.push(obj);
					}
					
				}
			//user does not have roles to access kb so break
				else if(!getKB.hasNext()) {
					break;
				}
			}
		//if array is length is not 0 we assume they had access
			if(kbList.length != 0) {
				logText += 'Answer: ' + JSON.stringify(kbList) + '\n';
				gs.log(logText,'kbResolveCriteriaCheck');
				return new JSON().encode(kbList);
			}
		//if array length is 0 they had no access to any of the attached KBs
			else {
				logText += 'Returning false' + '\n';
				gs.log(logText,'kbResolveCriteriaCheck');
				return 'No Access';
			}
		},
		
		type: 'kbResolveCriteriaCheck'
	});

 

Appropriate section of client script (I'm just trying to return it as a list of infomessages right now):

function kbCheckResult(response) {
				var answer = response.responseXML.documentElement.getAttribute("answer");
				//answer = JSON.stringify(answer);
				//answer = answer.toString();
				answer = answer.evalJSON();
				
				if (answer == 'No Attached KB') {
					alert('Please attach a knowledge article to this incident for the caller before resolving');
					return false;
				}
				else if (answer == 'No Access') {
					alert('The caller does not have access to view the attached knowledge articles\nPlease select a different article');
					return false;
				}
				else {
					for (var i=0; i< answer.length; i++) {
						g_form.addInfoMessage(answer[i].number + ': ' + answer[i].short_desc);
					}
				}
			}
		}
1 ACCEPTED SOLUTION

DScroggins
Kilo Sage

Hello Simon,

 

When you return either Arrays or Objects to a client script via GlideAJAX you need to stringify the returned value. Then in the client script you can parse the result and do with it as you wish. For example in the provided the Script Include is attempting to return the KB List using the following:

return new JSON().encode(kbList);

Instead of the above try the following:

return JSON.stringify(kbList);

 

Then in your Client Script you are attempting to determine one of three possible return values: 1. 'No Attached KB' 2. 'No Access' or 3. An Array of Objects. Because of that I would compare the returned 'answer' to the possible strings first then attempt to parse and utilize the array like so:

var answer = response.responseXML.documentElement.getAttribute("answer");

if (answer == 'No Attached KB') {

alert('Please attach a knowledge article to this incident for the caller before resolving');
	
}
else if (answer == 'No Access') {

alert('The caller does not have access to view the attached knowledge articles\nPlease select a different article');
					
}
else {

    answer = JSON.parse(answer);
				
    for (var i=0; i< answer.length; i++) {

	   g_form.addInfoMessage(answer[i].number + ': ' + answer[i].short_desc);

    }
				
}

 

Please let me know if this helps.

 

--David

View solution in original post

3 REPLIES 3

Roel3
Mega Guru

Hi Simon,

I usually just send the array with a join(",") and split the info again on client side.

 PS: Using glidedialogwindow with the ui page 'glide_confirm_standard' or 'glide_info' might improve your client experience icw alert;

https://docs.servicenow.com/bundle/helsinki-application-development/page/script/client-scripts/refer...

Regards Roel

DScroggins
Kilo Sage

Hello Simon,

 

When you return either Arrays or Objects to a client script via GlideAJAX you need to stringify the returned value. Then in the client script you can parse the result and do with it as you wish. For example in the provided the Script Include is attempting to return the KB List using the following:

return new JSON().encode(kbList);

Instead of the above try the following:

return JSON.stringify(kbList);

 

Then in your Client Script you are attempting to determine one of three possible return values: 1. 'No Attached KB' 2. 'No Access' or 3. An Array of Objects. Because of that I would compare the returned 'answer' to the possible strings first then attempt to parse and utilize the array like so:

var answer = response.responseXML.documentElement.getAttribute("answer");

if (answer == 'No Attached KB') {

alert('Please attach a knowledge article to this incident for the caller before resolving');
	
}
else if (answer == 'No Access') {

alert('The caller does not have access to view the attached knowledge articles\nPlease select a different article');
					
}
else {

    answer = JSON.parse(answer);
				
    for (var i=0; i< answer.length; i++) {

	   g_form.addInfoMessage(answer[i].number + ': ' + answer[i].short_desc);

    }
				
}

 

Please let me know if this helps.

 

--David

Community Alums
Not applicable

Thanks David, this is what I ended up doing, I made my answer a JSON payload and then used JSON.parse client side to handle the returned data.