Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

How to dynamically update content block based on selected option using Jelly?

zhen
Kilo Explorer

Hi there!

I am trying to write a script that will update the content in a dynamic content block based on the option selected.  The option should query back to a table and look for results related to the table.  I am getting stuck on the onchange function...

 

<g:evaluate var="jvar_tasktypes" object="true" jelly="true">
var tables = 'u_billing_information';
var obj=[];
var gr= new GlideAggregate('u_billing_information');
  gr.groupBy('u_business_unit');
  gr.query();
  while(gr.next()){
    obj.push([gr.getValue('u_business_unit'),gr.getDisplayValue('u_business_unit')]);
  }
  obj;
</g:evaluate>

 <select id='filter_task_type' class='select2-search' onchange='filterTaskType()'>
        <option value="">All</option>
        <j:forEach var="jvar_tasktype" items="${jvar_tasktypes}">
            <option value="${jvar_tasktype[0]}">${jvar_tasktype[1]}</option>       
        </j:forEach>
    </select>  
<script>
function filterTaskType(){
 var taskType = $j('#filter_task_type').val();
<g:evaluate var="jvar_gr" object="true">
   var gr = new GlideRecord("u_billing_information");
   gr.addQuery('u_business_unit', taskType);
   gr.query();
   gr;
</g:evaluate>
<j:if test="${jvar_gr.next()}">
   hello I see you
</j:if>

}

</script>

 

 

1 ACCEPTED SOLUTION

ChrisBurks
Giga Sage

Hi Zhen,

 

There two issues here:

  1. Jelly processes server side before the page is rendered. Therefore making a change to the select drop down won't trigger anything unless there is some sort of page refresh and "caching" of the data to pass (many times done via url params in ServiceNow). 
  2. Even if it were able to pass the data directly, the filterTaskType function still wouldn't display because there is no return of the data because the j:if statement is still inside the function. 

There are a few ways to resolve this. One popular way is to use a combination of a Client Callable Script Include and a GlideAjax call to that script include. Important Note: Script Include must be Client Callable. That's accomplished by checking that field on the Script Include form when creating it.

 

Example:

Note: This is based on your posted script. However, some things are modified because I don't have the same environment, such as tables, as you. The concepts are still the same.

Client Callable Script Include:

var BillingInfoUtil = Class.create();
BillingInfoUtil.prototype = Object.extendsObject(AbstractAjaxProcessor, {
	
	getBillingInfo: function(){
		var taskType = this.getParameter('sysparm_task_type');
		gs.log("Task Type: " + taskType, "Select EX")
		var gr = new GlideRecord("incident");
		//this gliderecord setup is assuming you're expecting one record exists that meets the
		//criteria. Adjust if necessary
		gr.get(taskType);
		var fields = ['number','short_description','state']
        var bu = {};
		if (gr.getUniqueValue()){
			//this is an assumption. You'll need to determine what your needs are;
			fields.forEach(function(field){
				bu[field] = gr.getValue(field)
			})
			
		}
		
		return JSON.stringify([bu]);
		
	},

    type: 'BillingInfoUtil'
});

 

Dynamic Content Block using GlideAjax:

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
	<g:evaluate var="jvar_tasktypes" object="true" jelly="true">
		// Changed to GlideRecord for demo purpose as I don't have the same tables or setup as you
		var objs = [];
		var gr= new GlideRecord('incident');
		gr.groupBy('number');
		gr.setLimit(5);
		gr.query();
		while(gr.next()){
		objs.push({'sys_id': gr.getValue('sys_id'),'number':gr.getDisplayValue('number')});
		}
		objs;
	</g:evaluate>
	<div class="container">
		<div class="col-md-3">
			<div class="panel-body">
				<h4>Select an Incident</h4>
				<select id='filter_task_type' class='select2-search form-control'  onchange='filterTaskType()'>
					<option value="">All</option>
					<j:forEach var="jvar_tasktype" items="${jvar_tasktypes}">
						<option value="${jvar_tasktype.sys_id}">${jvar_tasktype.number}</option>       
					</j:forEach>
				</select>  
			</div>
		</div>
		<div class="col-md-9">
			<div class="panel-body">
				<h3>Incident Details</h3>
				<div id="incDetails">
					<div class="list-group"></div>
				</div>
			</div>
		</div>
	</div>
	<script>
		function filterTaskType(){
			var container = document.querySelector('.container');
			var taskType = container.querySelector('#filter_task_type').value;
		    var incDetails = container.querySelector('.list-group');
			
		  //Here is where the GlideAjax comes in instead of g:evaluate
		    var ga = new GlideAjax('BillingInfoUtil');
			ga.addParam('sysparm_name', 'getBillingInfo');
			ga.addParam('sysparm_task_type', taskType);
			ga.getXML(callback);
			
			function callback(response) {
			  var result = response.responseXML.documentElement.getAttribute("answer");
		      var details = JSON.parse(result);
		      var keys = Object.keys(details[0]);
		      var html = [];
		      keys.forEach(function(key){
				 var label = key.toUpperCase().replace("_", " ");
		         var text = details[0][key];
		         html.push('<div class="list-group-item"><h4 class="list-group-item-heading">'+ label + '</h4>');
				 html.push('<p class="list-group-item-text">' + text + '</p></div>');
			  });
		       incDetails.innerHTML = html.join("");
			  
			}

		}

	</script>

</j:jelly>

 

Screencast of result:

View solution in original post

11 REPLIES 11

ChrisBurks
Giga Sage

Glad I could help!

Naples1966
Giga Contributor

hi,

J'am interesting for this example . because, I look for the method to update the selected data of business service to send it to the script. this allows to extract records of incidents if this selected data is equal business service incident OR internal service incident to display the results in the report

Is it possible ?  If yes, may you send me the script, please ? beacause, I don't know tje script well !....  Of, I try to work it  !  🙂

 

Thank you in advance for all.

 

B.D from paris