Service Catalog variable cleared after request submission.

Damian17
Giga Contributor

Dear ServiceNow Specialists, 

I faced the issue with the ServicePortal form. What I wanted is to based on one reference field from cmdb_ci_appl table, auto-populate values in variables on the form. 
I used Script Include to gather values and Catalog Client Script to populate them.

The functionality works fine, however, when the form is submitted, values which reference sys_choice table are not saved. If I change the value in these fields, it will save it to a variable. If I don't do anything with them, they will be saved as empty on the requested item. 

With Script Include, I'm feeding the Catalog Client Script with Value of the sys_choice record and Label of it. Both Scripts below.

Script Include:

var appl_data;

function onChange(control, oldValue, newValue, isLoading) {
	
	g_form.setValue('var_category','','');
		g_form.setValue('version','');
	
   if (isLoading) {
      return;
   }
	
	// new GlideAjax object referencing name of AJAX script include 
var ga = new GlideAjax("ApplicationPortfolioReview"); 
// add name parameter to define which function we want to call 
// method name in script include will be getFavorites
ga.addParam("sysparm_name","getApplData");
ga.addParam("sysparm_bs", newValue);

// submit request to server, call ajaxResponse function with server response
 
ga.getXML(ajaxResponse);
 
	function ajaxResponse(serverResponse) {

	  // get result element and attributes
	  var result = serverResponse.responseXML.getElementsByTagName("result");
		console.log(result);
	  var message = result[0].getAttribute("message");

	  //check for message attribute and alert user
	 // if(message) alert(message);

	  // get application data 
	  appl_data = serverResponse.responseXML.getElementsByTagName("result");
      if (appl_data.length>1) {
		  
		g_form.setValue('var_lifecycle_status', appl_data[1].getAttribute("install_status_value"), appl_data[1].getAttribute("install_status_label"));
		g_form.setValue('var_operational_status', appl_data[1].getAttribute("operational_status_value"), appl_data[1].getAttribute("operational_status_label"));
		g_form.setValue('var_manufacturer', appl_data[1].getAttribute("manufacturer_value"), appl_data[1].getAttribute("manufacturer_label"));
		g_form.setValue('var_owned_by', appl_data[1].getAttribute("system_owner_value"), appl_data[1].getAttribute("system_owner_label"));
		g_form.setValue('var_managed_by', appl_data[1].getAttribute("system_admin_value"), appl_data[1].getAttribute("system_admin_label"));
		g_form.setValue('var_version', appl_data[1].getAttribute("version"));
		alert('operational_status_value: ' + appl_data[1].getAttribute("operational_status_value") +'\ninstall_status_value: ' +appl_data[1].getAttribute("install_status_value"));
	  }
		
	}
}

Catalog Client Script:

var ApplicationPortfolioReview = Class.create();
ApplicationPortfolioReview.prototype = Object.extendsObject(AbstractAjaxProcessor, {
	getApplData: function() { // build new response xml element for result
		
		result.setAttribute("message", "returning users for ");
		
		//table to query: cmdb_ci_appl
		//param = sys_id of program group
		//return ...
		var appl_sys_id = this.getParameter('sysparm_bs');
		
		if (!appl_sys_id) {
			return false;
		}
		
		var AP = new GlideRecord('cmdb_ci_appl');
		
		if (!AP.get(appl_sys_id)) {
			return false;
		}
		
		var result = this.newItem("result");
		result.setAttribute("message", "returning users for " + appl_sys_id);
		
		this._addDetails(AP);
		
	},
	// all items are returned to the client through the inherited methods of AbstractAjaxProcessor
	_addDetails: function(AP) {
		var appl_data = this.newItem("result");
		appl_data.setAttribute("install_status_label", AP.install_status.getDisplayValue());
		appl_data.setAttribute("install_status_value", AP.install_status);
		appl_data.setAttribute("operational_status_label", AP.operational_status.getDisplayValue());
		appl_data.setAttribute("operational_status_value", AP.operational_status);
		appl_data.setAttribute("manufacturer_label", AP.manufacturer.getDisplayValue());
		appl_data.setAttribute("manufacturer_value", AP.manufacturer);
		appl_data.setAttribute("system_owner_label", AP.owned_by.user_name);
		appl_data.setAttribute("system_owner_value", AP.owned_by);
		appl_data.setAttribute("system_admin_label", AP.managed_by.user_name);
		appl_data.setAttribute("system_admin_value", AP.managed_by);
		appl_data.setAttribute("version", AP.version);
	},
	type: 'ApplicationPortfolioReview'
});

Please, help me to troubleshoot this, or point what should I correct.

1 ACCEPTED SOLUTION

Hello Omkar,

I marked your answer as correct, but the true solution, according to best practice, required a little bit different approach. Please, let me explain. 

To auto-populate and keep value in Reference type field to sys_choice table, on Service Portal form you need to gather:

  • Label of the sys_choice record,
  • sys_id of the sys_choice record.

I did it in Script Include by using a query for each of these kinds of fields. They are described as IS and OP

var ApplicationPortfolioReview = Class.create();
ApplicationPortfolioReview.prototype = Object.extendsObject(AbstractAjaxProcessor, {
	getApplData: function() { // build new response xml element for result
		
		result.setAttribute("message", "returning users for ");
		
		//table to query: cmdb_ci_appl
		var appl_sys_id = this.getParameter('sysparm_bs');
		
		if (!appl_sys_id) {
			return false;
		}
		
		var AP = new GlideRecord('cmdb_ci_appl');
		
		if (!AP.get(appl_sys_id)) {
			return false;
		}
		
		//sys_id of recrod from sys_choice table
	var IS = new GlideRecord('sys_choice');
		IS.addEncodedQuery('name=cmdb_ci_appl^element=install_status^inactive=false^value='+AP.install_status);
		IS.query();
		if(!IS.next()){
			return false;
		}
		
		//sys_id of record from sys_choice table
			var OP = new GlideRecord('sys_choice');
		OP.addEncodedQuery('name=cmdb_ci^element=operational_status^inactive=false^value='+AP.install_status);
		OP.query();
		if(!OP.next()){
			return false;
		}
	
		var result = this.newItem("result");
		result.setAttribute("message", "sys_id of CI record " + appl_sys_id);
		
		this._addDetails(AP,OP,IS);
		
	},
	// all items are returned to the client through the inherited methods of AbstractAjaxProcessor
//proper variable feed to the function
	_addDetails: function(AP,OP,IS) {
		
		var appl_data = this.newItem("result");
		
		appl_data.setAttribute("install_status_label", AP.install_status.getDisplayValue());
		appl_data.setAttribute("install_status_value", IS.sys_id);
		appl_data.setAttribute("operational_status_label", AP.operational_status.getDisplayValue());
		appl_data.setAttribute("operational_status_value", OP.sys_id);
		appl_data.setAttribute("manufacturer_label", AP.manufacturer.getDisplayValue());
		appl_data.setAttribute("manufacturer_value", AP.manufacturer);
		appl_data.setAttribute("system_owner_label", AP.owned_by.user_name);
		appl_data.setAttribute("system_owner_value", AP.owned_by);
		appl_data.setAttribute("system_admin_label", AP.managed_by.user_name);
		appl_data.setAttribute("system_admin_value", AP.managed_by);
		appl_data.setAttribute("version", AP.version);
	},
	type: 'ApplicationPortfolioReview'
});

For unknown, at least for me, reason, a reference to sys_choice table require different treatment, because in the example of another Reference type field - manufacturer, feeding it with label and value was enough, no sys_id required. ¯\_(ツ)_/¯

I could use only the sys_id, without using of Label of the record, but in that case, the system was doing its own query on every change of the form to find the Label, and I prefer to do it on my own. I observed this in the browser Network activities, that every time the Catalog Client script was triggered, another query was launched.

That is why, feeding the field only with sys_id will do the job but from the best practices point of view, it is not enough.

* I've noticed, that in my question I described Catalog Client Script as Script Include and vice versa, I'm sorry for the confusion.

I appreciate your input here, cause I was missign this peace of the puzzle, Omkar. 

Sincere, Thank You.

Damian

View solution in original post

6 REPLIES 6

Omkar Mone
Mega Sage

Hi 

So you are saying that you are setting value to Select Box variable? If yes then please do that with addOption method of g_form - 

Check the link for better understanding - addOption

 

Regards,

Omkar Mone

What I wanted, is to set value from record picked in Application Name (from cmdb_ci_appl table) to Lifecycle Status and Operational Status. 
LS and OS are reference fields to the sys_choice table.

find_real_file.png

And that how it looks on the requested item:

find_real_file.png

I've tried to use the addOption method, but I don't think it can be used here to populate and keep the values saved in variables.

Hi 

If they are reference field, make sure you are returning sys_id from the Script include and then setValue is correct, but set only the sys_id and nothing else.

 

Regards,

Omkar Mone

It works!

find_real_file.png

Thank you a lot, Omkar.

Regards,

Damian