petercawdron
Kilo Guru

Although this will work for multiple versions of ServiceNow it was originally designed to resolve a problem with the London release where dates in multi-row variable sets weren't showing correctly in the variable formatter for a record producer. 

ServiceNow's default variable formatter looks like this...

find_real_file.png

But the service portal comes with a variable formatter as well, and it renders nicely in the back end, looking like this...

find_real_file.png

This is a good example of how portal widgets can be integrated into UI macros and used within regular forms at the back-end of ServiceNow. This works for BOTH catalog items and record producers.

All that's needed is a blank portal (so there's no toolbar/navigation available) and a script that can account for the loading of the portal after the main form has rendered.

Here's the code for the UI Macro (but the attached update set contains the whole package, all that remains is to add it to your form)

<?xml version="1.0" encoding="utf-8"?>  
<j:jelly xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null" trim="false">  

	<h3>Variables</h3>
	<iframe src="/generic?id=variable_editor${AMP}table=TableName${AMP}sys_id=UniqueValue" id="variableFrame" style="width:100%;"></iframe>

	<script>
		//////////////////////////////////////////////////////////////
		//On load, set up the iframe source
		(function(){
			//set iframe source
			var src = jQuery('iframe#variableFrame').attr('src');
		 
			// get the table name from the URL, for example, /sc_req_item.do
			var pathName = window.location.pathname;
			pathName = pathName.substr(1,pathName.length-4);
		
			//get the sys_id from the URL parameters
			var location  = window.location.href;
			var locParams = location.split('?')[1].split('$[AMP]');
			var keyVal = {};
			locParams.forEach(function(param){var thisKeyVal = param.split('='); keyVal[thisKeyVal[0]] = thisKeyVal[1]})
		
			src = src.replace('TableName',pathName)
			src = src.replace('UniqueValue',keyVal.sys_id || 'UNKNOWN')

			jQuery('iframe#variableFrame').attr('src',src)
		})()	
		
		//////////////////////////////////////////////////////////////
		//After loading the form, resize the parent iframe
		window.addEventListener('DOMContentLoaded', function(e) {
			
			hasAngularLoaded(0)
		
		} );
		
		//Loop until ServiceNow angular has finished loading
		function hasAngularLoaded(counter){
			var haveServiceNowMessagesLoaded = jQuery('now-message',jQuery('iframe#variableFrame').contents()).length
			if(haveServiceNowMessagesLoaded==0){
				if(parseFloat(counter/16) != 1){ //wait for a maximum of eight seconds
					counter++;console.log('%c'+counter,'color:red')
					setTimeout(function(){hasAngularLoaded(counter)}, 500);
				}
			}else{
				//to be safe, we'll give angular another half a second for the widget to render properly
				setTimeout(function(){
					//update the height based on the location of the save button
					jQuery('button[name="save"]',jQuery('iframe#variableFrame').contents()).html('Only Save Changes to Variables')
					var whichHeight = jQuery('main[data-page-title="Variable Editor"]',jQuery('iframe#variableFrame').contents()).height() || 100;
					jQuery('iframe#variableFrame').css('height', (whichHeight+40)+'px');
				}, 500);
			}
		}
		
	</script>

</j:jelly> 

Catalog policies and scripts will run as normal and can be separated between when they're active. The only limitation is changes to variables need to be saved separately (but don't force a browser refresh)

Have fun

Version history
Last update:
‎08-19-2019 09:33 PM
Updated by: