The CreatorCon Call for Content is officially open! Get started here.

Michael Jones -
Giga Sage

Multi-Row variable sets were introduced in London and were something of a game changer; they finally provided an in-platform method for capturing repeatable datasets dynamically. Before they were an option you had to go to somewhat extreme measures to achieve the same functionality with a custom solution, which came with its own set of challenges and drawbacks. Suffice to say they are a fantastic addition to the platform but, there are some situations where they don't function the way you would hope (or expect). 

A good example of this would be the fact that when you write a catalog client script within the Multi-Row Variable set, by default the script can only access and influence variables that are included in the MRVS. If you try to use a standard method and call a variable that is outside of the MRVS, you get no results. Things like g_form.getValue() and g_form.setValue() return no results (and no hard errors). Most of the time this isn't really an issue, but in certain circumstances you might find it beneficial to either pull in existing values from your catalog item, or to set values on the catalog item, in response to selections your user is making on the MRVS. 

If your catalog item is being used via the Service Portal, unfortunately you are still out of luck, at least without some heavy customizations that are strongly discouraged. If however your item is being used via the UI then you can accomplish this with a relatively easy configuration! One caveat is that this is not a best-practice as it requires the use of the window object so, use with careful consideration. 

Native UI: 

For example, say you want to use a value selected in a select box named "hardware_type" to set the value of a select box called "type" on your MRVS when a new row is added, you could do the following. 

Create the variable on the Catalog Item and populate it with whatever options you want to include. 

Create the variable on the MRVS with no options. 

Create an On Load Catalog Client Script on your MRVS.

Enter a script like this:

function onLoad() {
   var option = parent.g_form.getValue('hardware_type');
   g_form.addOption('type', option, option);
}

For the next step, you have two options.

You can configure the catalog client script form to include the Isolate Script field. Once it is visible, uncheck it.

Alternately you can view the script in the list view, add the field to the list and set it to false from there. 

The result will be something like this: 

find_real_file.png

The reason this works? The MRVS is called within an iframe, which is isolated from the main window and prevents scripts called locally from interacting with elements outside of the iframe. By allowing the use of Globals and calling window.parent before the function you pass the call to the parent and the response is passed back to the child. 

While the example I provide is somewhat simple, the basic principle can be used to accomplish some interesting results. In fact the process can be used in both directions; by calling window.parent.setValue() you can update values on the Catalog Items, based on selections in the MRVS, in real time. For example you could keep a running total cost of all items added via the MRVS for validation. 

While this isn't something I would suggest using excessively, there are some situations where there simply isn't another way to achieve the same results so, it's a useful trick to have available.  

Update for Service Portal:

For those looking for a solution that works in the Service Portal as well as the native UI, there are a couple of methods floating around. One is mentioned in the comments here by Rupam;  they mention that something like this might be a workaround for the portal as an onload script in the variable set: 

var catItem = spThis.angular.element(spThis.$('#sc_cat_item').find('sp-variable-layout')[0]).scope();
var parent_g_form = catItem.getGlideForm(); 

parent_g_form.setValue('field', 'value');

I've seen this approach work, and also not work, and I wasn't able to explain why in either case so, I've kept searching. 

While trying to do something unrelated I stumbled across a method that seems to work reliably, at least thus far. 

You would need to create an Onload script in your catalog item, with isolate script set to false: 

function onLoad() {
   //We need to make the g_form object for the parent item available for later
	
    this.cat_g_form = g_form;
   
}

Once that is in place, you can use something like in a script on the MVRS (also set to isolate script false). This example sets a field on the parent catalog item when a particular checkbox is selected on an MVRS row, and (in combination with the above script) works for both Portal and Native UI. 

function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') {
        return;
    }

    //Service Portal logic
    if (this) {
        this.cat_g_form.setValue('some_textfield', 'Some option included in MRVS');
    } else {
		//Native UI logic
        parent.g_form.setValue('some_textfield', 'Some option included in MRVS');
    }
}

This has been working reliably in all of the situations where I've used it, so I wanted to share this method as well. 

If you found this article helpful or useful, please be kind and click appropriately. If you found it really useful, you could always use the 3-dot menu to bookmark it for later! 

Michael Jones - Proud member of the CloudPires team!

Comments
Anjaneyulu Muv1
Tera Expert

Hi,

I have one issue about this.

i have company variable outside MRVS.

in MRVS i have user field. i want to use company value in user field reference qualifier.

How to get that value.Please help me.

 

Thank you.

Rupam_39
Giga Guru

Hi Michael,

I was chasing this question for quite a long time, until today.
I am currently working on Connected Workplace (ServiceNow store application) for one of my clients. In this application, I was looking at one of the catalog that was pre-build and it did contain MRVS.

To my surprise, I found that they were populating the fields in MRVS based on the variables of the catalog and they were doing this both on the portal and the Native UI. I went ahead and checked the onLoad client script in the MRVS and I found below.

function onLoad() {
	var siResponse = [];
	var spThis = this;
	
	// Service Portal Section
	if(spThis){

		var catItem = spThis.angular.element(spThis.$('#sc_cat_item').find('sp-variable-layout')[0]).scope();
		var parent_g_form = catItem.getGlideForm();

		var parentRequestDateSP = parent_g_form.getValue('requested_move_date');
		var parentSiteSP = parent_g_form.getValue('site');
		var parentFloorSP = parent_g_form.getValue('floor');
		var parentCostCenterSP = parent_g_form.getValue('cost_center');
		var parentCvxLocationSP = parent_g_form.getValue('location');

		g_form.setValue('employee_requested_move_date', parentRequestDateSP);
		g_form.setValue('to_home_base', parentSiteSP);
		g_form.setValue('to_floor', parentFloorSP);
		g_form.setValue('user_cost_center', parentCostCenterSP);

		if (parentCvxLocationSP == 'non_c') {
			var ga = new GlideAjax('DateUtils');
			ga.addParam('sysparm_name','getNonCLocation');
			ga.getXML(getData);
		}
	} 
	
	//Native UI Section
	else {
		var parentRequestDate = window.parent.g_form.getValue('requested_move_date');
		var parentSite = window.parent.g_form.getValue('site');
		var parentFloor = window.parent.g_form.getValue('floor');
		var parentCostCenter = window.parent.g_form.getValue('cost_center');
		var parentCvxLocation = window.parent.g_form.getValue('location');

		g_form.setValue('employee_requested_move_date', parentRequestDate);
		g_form.setValue('to_home_base', parentSite);
		g_form.setValue('to_floor', parentFloor);
		g_form.setValue('user_cost_center',parentCostCenter);

		if (parentCvxLocation == 'non_c') {
			var ga2 = new GlideAjax('DateUtils');
			ga2.addParam('sysparm_name','getNonCLocation');
			ga2.getXML(getData);
		}

	}
	function getData(response){
		var answer = response.responseXML.documentElement.getAttribute("answer");
		siResponse = answer.toString().split('||');
		g_form.setValue('to_home_base',siResponse[2]);
		g_form.setValue('to_floor',siResponse[1]);
		g_form.setValue('to_space',siResponse[0]);

		g_form.setReadOnly('to_home_base','true');
		g_form.setReadOnly('to_floor','true');
		g_form.setReadOnly('to_space','true');

		g_form.setVisible('to_home_base','false');
		g_form.setVisible('to_floor','false');
		g_form.setVisible('to_space','false');

		g_form.setMandatory('notes', true);
		g_form.showFieldMsg('notes','Include the Non-C Address','error',true);
	}
}

  

After this I tried analyzing the below 2 lines. I googled it, but no luck. So I tried googling it with "how to pass data to multi row variable set client script from catalog variables"  and I came across your article, but for you as well it wasn't working on the portal.

var catItem = spThis.angular.element(spThis.$('#sc_cat_item').find('sp-variable-layout')[0]).scope();
var parent_g_form = catItem.getGlideForm(); 

Hopefully this helps someone. I am still looking for information on this getGlideForm() and the angular dot-walking on the DOM to the MRVS.

Michael Jones -
Giga Sage

Excellent, thank you for sharing this information. I'm sure others will find it useful as well!

I'll definitely spend some time looking into this as this has been a (minor) thorn in my side far too often 🙂

Thanks again!

Uday Singh2
Mega Explorer

It worked !!

Michael Jones -
Giga Sage

Updated to include a reliable way to access Catalog Item elements from a Multi-Row Variable Set in the Service Portal as well as the Native UI.

michelhanna
Kilo Guru

Hi,

This works! The only issue is that the service portal part does NOT work in ATF.

The following part does not return a value

spThis.$('#sc_cat_item').find('sp-variable-layout')[0]

I also tried replacing the $ with jQuery but still no luck.

 

Have you experienced this in ATF?

michelhanna
Kilo Guru

Starting Quebec, you can now use the g_service_catalog API which is available in all environments, such as, Service PortalNow PlatformWorkspace, and Now® Mobile.

It's also not working on ATF, and I will have to report this to ServiceNow to fix.

https://developer.servicenow.com/dev.do#!/reference/api/rome/client/g_service_catalogClientAPI#g_service_catalog-getValue_S?navFilter=g_service_catalog

Rupam_39
Giga Guru

Hi Michelhanna,

Yes, starting with Quebec we have this g_service_catalog API but it is available only for getting the value using the "getValue(String variableName)" and doesn't have setValue function.

radt
Kilo Guru

hello, I have cost field in the row of MRVS and for every row we will add different cost.. 

Lets say cost -- 100 in one row and cost 200 in other row.. I want to add the cost and the total should populate in a new variable below. Is it possible?

find_real_file.png

 

You can see cost 100 and 300. When ever a row is added and they add cost it should add all the costs and update in Total cost. Do you have any idea on this?

Rupam_39
Giga Guru

Hi @radt ,

Apologies for the delayed response
Use as below

var mrvsRows = g_form.getValue("mrvs_name");
//The above will return a string in the form of array and objects. Now you will have to parse it

var oMrvs = JSON.parse(mrvsRows);
var sum = 0;
for(var i in oMrvs) {
	sum += oMrvs[i]["cost_field_name"]
}

g_form.setValue("total_cost_field_name", sum);

Thanks
Rupam

Pritam Mangrul1
Tera Expert

This worked for me, Thanks for sharing.

Bhavana Reddy
Mega Guru

Hye did you get the solution for this?

ray evans
Tera Guru

Hi

 

How would I use this to update quantity based on mrvs rows, in Service Portal/Employee Centre?

Sivakrishna
Kilo Sage

Hi @Michael Jones - 

I have also used below line of code in onSubmit() catalog client script of a multi row variable set to set the variable outside the MRVS.

function onSubmit(){

var catItem = spThis.angular.element(spThis.$('#sc_cat_item').find('sp-variable-layout')[0]).scope();
var parent_g_form = catItem.getGlideForm(); 

parent_g_form.setValue('field', 'value');

}

Its working on portal side and populated the field value in the case form when I am submitted the Record producer but whenever the case is opened in the native UI and edited the Multi Row Variable set, while submitting a MRVS in case form, some times it is showing script error like this "onSubmit script error: TypeError: Cannot read properties of undefined (reading 'element'):". I am enclosed error screenshot.

 

Please help me to fix this issue.Error in Finance case of Create New Vendor.JPG

 Thanks in advance.

 

With Regards

 

P. Siva.

Community Alums
Not applicable

Great, thank you so much for sharing!

Version history
Last update:
‎02-08-2020 12:15 PM
Updated by: