Maik Skoddow
Tera Patron
Tera Patron

find_real_file.png

For Service Catalog Items with many fields, it could be helpful to re-order an existing Requested Item by prefilling the new request form with the same values of the RITM to be cloned. This is always useful, for example, if you do not want to enter everything again manually. There are several approaches to this challenge, and my article describes one of them.

        
Table of Contents

 

Approach

 

On RITM records we need a button (UI Action) "Clone" which pulls all variable values and put them into a session object for a transfer to the catalog form. Of course, it would also be possible to fetch all the data on client-side with an GlideAjax call, but transferring the data from the server to the client via a session object is more elegant, secure and error-prone. 

On the Catalog Item an additional Client Script is required to recognize the variable value transfer and to fill that values into the form. That Client Script is contained in a Variable Set. In this way, the Variable Set can be easily embedded in each Catalog Item, which should support prefilling of the form elements.

 

 

Limitations

 

That approach only works for requests that consist of a single catalog element and therefore do not represent a bundle or an order guide. In addition, the "Clone" button is only available in the UI16 and therefore not in the Service Portal or in a Workspace.

 

 

Solution

 

Script Include

 

The Script Include CatalogUtils provides a method getVariables() that returns all variables of a given RITM as stringified array of objects. Each of these objects corresponds to a respective Catalog Variable and has the following properties:

strType:
integer value of the variable type or "MVRS" in case the Catalog Item contains Multirow Variable Sets

strName:
variable name

strQuestionText:
label text for a variable

strValue:
the underlying variable value, for example for a reference variable it would be the Sys ID of the target record

strDisplayValue:
the text which is rendered for the variable, for example for a reference variable pointing to the sys_user table it would be the complete name of the referenced user

 

You can go to https://github.com/mskoddow/sn-scripts/blob/master/CatalogUtils.js  for loading the source code of that Script Include.

 

 

UI Action

 

Create a new UI Action with the following parameters:

 

Name Clone
Table Requested Item (sc_req_item)
Form Button (checked)
Show update (checked)
Condition (define an appropriate condition here to make the UI action available only for authorized users)
Script
//store all variable values in a session object
gs.getSession().putClientData(
  'variable_values', 
  new CatalogUtils().getVariables(current)
);

//redirect to the catalog form 
//URL parameter sysparm_clone indicates the request for prefilling
gs.setRedirect(
  'com.glideapp.servicecatalog_cat_item_view.do?sysparm_id=' + 
  current.cat_item + 
  '&sysparm_clone=true'
);

 

 

Variable Set

 

Create a Single-Row Variable Set:

 

find_real_file.png

 

and name it "Basic Initialization" (or choose another name). 

 

This Variable Set will only contain the following Catalog Client Script.

 

 

Catalog Client Script

 

Go to Related List "Catalog Client Scripts" and create a new record:

 

find_real_file.png

 

with the following parameters:

 

Name Prefill form with variable values
Applies to Variable Set
UI Type Desktop
Type onLoad
Variable Set Common Initialization
Applies on a Catalog Item view (checked)
Script
function onLoad() {
	var objUrl = new GlideURL();

	objUrl.setFromCurrent();

	var isCloneMode  = objUrl.getParam("sysparm_clone") || '';
	var strVariables = g_user.getClientData('variable_values') || '';

	if (isCloneMode == 'true' && strVariables.length > 0) {
		var arrVariables = JSON.parse(strVariables);

		for (var i = 0; i < arrVariables.length; i++) {
			var strType         = arrVariables[i].strType || '';
			var strVarName      = arrVariables[i].strName || '';
			var strVarValue     = arrVariables[i].strValue || '';
			var strDisplayValue = arrVariables[i].strDisplayValue || '';

			//only try to fill form fields which are visible 
			if (!g_form.isDisabled(strVarName) && strVarValue.length > 0) {
				//for a reference field the display value also has to be set 
				//to prevent an additional request to the sever
				if (strType == '8' && strDisplayValue.length > 0) {
					g_form.setValue(strVarName, strVarValue, strDisplayValue);
				}
				else {
					g_form.setValue(strVarName, strVarValue);
				}
			}
		}
	}	
}
Screenshot MaikSkoddow_0-1671700707407.png

 

 

Add Variable Set to Catalog Items

 

The last step is adding the Variable Set to all Catalog Items, which should be able to prefill the form.

For testing purposes, you can pick the OOTB Catalog Item "Sample Item". Order one item and then clone it. In the order form for the clone, all fields should be filled correctly:

 

MaikSkoddow_1-1671700903137.png

 

 

A good practice for Catalog Management is to always include such a universal Variable Set into each Catalog Item. That way, you can implement or add common behaviors later without touching hundreds of Catalog Items.

 

Comments
Jason S1
Tera Contributor

Couldn't have been more perfect for what I was looking to do, thanks

Maik Skoddow
Tera Patron
Tera Patron

Glad that I could help!

Jason S1
Tera Contributor

You wouldn't happen to have an idea of how to make this work for a Multi Row Variable Set, would you?

Jason Stuart
Tera Expert

Maik, this is awesome.  Edited cause this does exactly as we needed to do.  This is amazing!

POOMANI NAGARAJ
Tera Contributor

Thankyou, It was incredible. Could you perhaps assist us with the Multi Row Variable Set in the similar way?

Maik Skoddow
Tera Patron
Tera Patron

@Jason S1 

All scripts have been modified to be able of handling multi-row variable sets (MRVS)

Jason Stuart
Tera Expert

Thank you Maik!  

tantony
Mega Guru

Maik,

I wanted to use this feature for creating a "Refund Item" UI action for billing admins. When customer asks for a refund for a purchased item , the billing admin opens the sc_request_item, clicks "Refund Item" UI action in the related list, It should open a new sc_request_item (not catalog item) within the same request, with all values copied over and admin should be able to edit quantity to negative and save the item. There is an existing UI action to download the altered billing information to be sent to customer

 

--Your code redirects to catalog item. How can I  redirect to the new cloned sc_request_item? I tried below code for redirection in the UI action but it is taking to original item:

gs.setRedirect(
'sc_req_item.do?sys_id='+ current.sys_id + '&sysparm_view=software_center&sysparm_clone=true'
);

 

--I could not find the documentation for 'sysparm_clone', Can you please give me the documentation link or link within Servicenow. We are in SanDiego 9

 

 

chunn
Tera Expert

@Maik Skoddow 

Hi ,  How can I use the above method in Service Portal?

priceless
Tera Expert

Hi @Maik Skoddow 

Customer not agreeing to create VSet and add to Catalogs, also this will be a manual work for all new catalogs so team has to add this Variable set to all existing and all future new catalogs. Do we have any other mechanism without VSet. Please suggest. 

Dave105
Kilo Guru

Hi Maik,

Can you think of anyway this could be replicated for Portal usage? We have a scenario where our customers have to enter individual requests but in some cases only a couple of fields need amending between requests. We were hoping to give the client the option so they can recall (clone) a previous request and simply amend the relevant fields to submit a new request, as per my question on forum: https://www.servicenow.com/community/sysadmin-forum/recall-a-previous-request-on-portal-to-complete-...

 

Regards

Dave

Lisa Goldman
Kilo Sage

Hello @Maik Skoddow 

Thank you so much for developing this clone UI action.  It has proven to be incredibly useful.  Could you please provide guidance on how we can modify the redirect to the new clone requested item after clicked on the Clone button, because we do not use an Add to cart function. 

 

LisaGoldman_1-1710869807945.png

 

Add to Cart function:

LisaGoldman_0-1710869655152.png

 

Maik Skoddow
Tera Patron
Tera Patron

@Lisa Goldman 

Unfortunately, I don't get your point. Please reach to me on LinkedIn to continue the discussion directly.

Toshiki Ohtsuka
Tera Explorer

Hello @Maik Skoddow 

Thank you for creating the clone functionality.

I am facing an issue where list-type variables are not being cloned. Could you please address this?

Venkata_ravula
Tera Contributor

Thank you for the detailed steps. I have implimented all of them but not able to achive the desired functionality. At the end when testing, I clicked on clone ritm ui action and I get redirected to the previous page/servicenow home.  For some reason I am not getting redirected to the catalog item. Any suggestions in what could be the problem and where to check is much appriciated.

Version history
Last update:
‎12-23-2022 09:59 PM
Updated by:
Contributors