rahulpandey
Kilo Sage

Hello Community,

Variable editors are really great way to show end user’s input to fulfillers. I get this question several times that, "hey Rahul, can we show variables on tasks other than catalog task" ?

Actually, there was a $500 bounty about this feature by @Robert Fedoruk  5 years ago. I was late to the party, 2 years late -_-

via GIPHY

Let me give you an example, suppose, a requestor creates an incident via record producer. Out of the box, there is variable editor for task extended tables. Hence, you can show variable editor for target record of the record producer, in this case incident.

Reference of out of the box variable editor :https://docs.servicenow.com/bundle/orlando-it-service-management/page/product/service-catalog-management/task/configure-default-variable-editor.html

However, what about incident task?  What if fulfiller working on incident task would like to see user’s input? Navigate to incident every time ?

via GIPHY

 

Below is a way to leverage UI macro to show variable editor on incident task

Example case,

User Rahul creates an incident using record producer

Record Producer

find_real_file.png

Resulting incident record

 find_real_file.png

Incident task

find_real_file.png

 

 

 

via GIPHY

Interesting right ? Let’s break this and find out how I have achieved it.

UI Macro

Name:CascadeFormatter

Script

<?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:requires name="scripts/js_includes_catalog.js" includes="true"/>
       <g:requires name="styles/${new CatalogCssSelector().getVariableCss()}" includes="true"/>
<g:requires name="scripts/classes/ServiceCatalogForm.js"/>


<g2:evaluate var="jvar_catalog_item">


             function eval_cat_item() {


               var cat_item = "";


var catItemProducedGr = new GlideRecord("sc_item_produced_record");


catItemProducedGr.addQuery("record_key", current.incident);


catItemProducedGr.query();


if (catItemProducedGr.next())


cat_item = catItemProducedGr.getValue("producer");


               return cat_item;


             }


             eval_cat_item();


       </g2:evaluate>




       <g2:evaluate var="jvar_cat_sets" jelly="true">


             var jvar_cat_sets = "";


             var gr = new GlideRecord("io_set_item");


             gr.addQuery("sc_cat_item", jelly.jvar_catalog_item);


             gr.query();


             while (gr.next()) {


                   if (jvar_cat_sets.length > 0)


                         jvar_cat_sets += ",";


                   jvar_cat_sets += gr.variable_set;


             }


             jvar_cat_sets;


       </g2:evaluate>




<div data-sn-macro-sys-id="${jvar_macro_sys_id}">


<g2:evaluate jelly="true"> var recordObject = new GlideRecord('incident');


recordObject.get(current.incident);


</g2:evaluate>


<j2:set var="ref" value="recordObject" />


<j:set var="jvar_producer_target_record" value="true"/>


<g2:client_script type="catalog_item" catalogItem="$[jvar_catalog_item]"/>

<g:inline template="catalog_ui_policy.xml"/>

<g2:render_component componentName="com.glideapp.servicecatalog.DefaultQuestionEditor"/>


</div>


</j:jelly>

Formatter

Screenshot:

find_real_file.png

Navigate to incident_task and add this formatter at the place of your choice

 find_real_file.png

 

Hopefully, this article would help to those who are searching for a solution to this problem 🙂

Comments
AdamCelli
Tera Contributor

Thank you for this guide! Do you know how to get this to work in a scoped app? Using the code as-is, I get an error in my browser console: Uncaught ReferenceError: g_sc_form is not defined.

JamesN1
Kilo Contributor

This really helped me out - thank you!

Sai89
Mega Expert

Hi,

where we need to do changes in script in macro if it is related to sn_hr_core_case(HR Case) this is under Human Resources: Core --> application and HR Task (u_hr_task) this is under Global --> application.

Please help me on this.

Thanks,

rah
Tera Explorer

Hi adam,
have you got any chance to get this worked in scopped application?

Regards,

Rajashekar

AdamCelli
Tera Contributor

Yes, I did actually succeed in getting it to work within a scoped app. The key was to make the UI Macro in the Global scope while making the Formatter in the app scope.

Thuy Thao
Tera Guru

Hello,

I followed your guides to show the variables from Record Producer to the Task Case form (sn_customerservice_task)

But I met this error. It said the fields which come from the Variables are not filled in, even though on the form, the values of theses fields already appeared.

Error

find_real_file.png

Variables fields

find_real_file.png

Do you have any idea on this error?

Thank you very much!

Olivia Williams
Tera Explorer

Did you ever get a solution on this? I have the same issue

Thuy Thao
Tera Guru

Hi Olivia,

Please access here. I raised this issue and this guy Sagar Pagar helped me.

However, his approach just makes the error alert disappear, but if we change the value of Variables within the Task Case form, it would not be saved.

If you not need to make any change for variables in level task case, you can set the variables readonly. And everything will make sense.

Regards

Vattem Sandhya
Tera Contributor

@rahulpandey 
 

Can you please help me how to use it for change task.

I have modified macro and replaced with change request in place of incident. But it is not working as expected

 

Thanks,

sandhya 

Rahul Pandey
Tera Explorer

Hi,

The key to above solution is the point that the parent record(incident in my case) should be create via a catalog.

To make this applicable on change request,

  • I have created a record producer on change_request table with applicable variables such as description and short description as show in below Image
  • Added the existing formatter to Change request form as shown below
  • Created a new UI macro(named Change Task Variable Editor Custom) as shown below and added on Change task form 
<?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:requires name="scripts/js_includes_catalog.js" includes="true"/>
       <g:requires name="styles/${new CatalogCssSelector().getVariableCss()}" includes="true"/>
<g:requires name="scripts/classes/ServiceCatalogForm.js"/>


<g2:evaluate var="jvar_catalog_item">


             function eval_cat_item() {


               var cat_item = "";


var catItemProducedGr = new GlideRecord("sc_item_produced_record");


catItemProducedGr.addQuery("record_key", current.change_request);


catItemProducedGr.query();


if (catItemProducedGr.next())


cat_item = catItemProducedGr.getValue("producer");


               return cat_item;


             }


             eval_cat_item();


       </g2:evaluate>




       <g2:evaluate var="jvar_cat_sets" jelly="true">


             var jvar_cat_sets = "";


             var gr = new GlideRecord("io_set_item");


             gr.addQuery("sc_cat_item", jelly.jvar_catalog_item);


             gr.query();


             while (gr.next()) {


                   if (jvar_cat_sets.length > 0)


                         jvar_cat_sets += ",";


                   jvar_cat_sets += gr.variable_set;


             }


             jvar_cat_sets;


       </g2:evaluate>




<div data-sn-macro-sys-id="${jvar_macro_sys_id}">


<g2:evaluate jelly="true"> var recordObject = new GlideRecord('change_request');


recordObject.get(current.change_request);


</g2:evaluate>


<j2:set var="ref" value="recordObject" />


<j:set var="jvar_producer_target_record" value="true"/>


<g2:client_script type="catalog_item" catalogItem="$[jvar_catalog_item]"/>

<g:inline template="catalog_ui_policy.xml"/>

<g2:render_component componentName="com.glideapp.servicecatalog.DefaultQuestionEditor"/>


</div>


</j:jelly>

Now it works on both change and change task

Change Request

Change Task

Remember: If you are creating change from template/interceptor then this may not work as it needs variables to work.

 

Hope this helps.

Regards,

Rahul

Ashwanth Parine
ServiceNow Employee
ServiceNow Employee

Hello Thuy,

 

Did you find the solution to save the variables from task record(child)

Community Alums
Not applicable

Hello Thuy,

I am also wondering if you were able to find a solution to save the variables when modified from the task (child) record?

Steve Kelly
Mega Sage

The solution to this issue I used was to ensure any variables that are mandatory are made mandatory by UI Policy, and not directly on the variable itself. This can take a bit of work, but I preferred to use this workaround instead of reverting to an earlier version of g_form which could potentially introduce other issues. 

Nick Parsons
Mega Sage

Thanks @rahulpandey for the post.

Just wondering if anyone else has noticed that client scripts with "Applies on Target Record" set to false (and a UI type of "All") are running on the record with this custom formatter? Does anyone know if it is possible to stop those client scripts from running, just like they don't run on the original target? I thought this line in the UI macro would stop them from running:

<j2:set var="jvar_producer_target_record" value="true" />

I was thinking that this would make the client scripts think that the current record is the target, so it wouldn't run the client script. But that unfortunately didn't seem to work as the client script is still running. 

Alb1
Tera Contributor

Hi guys!

I was wondering if someone was able to find a solution to save the variables when modified from the task (child) record??

Tim Grindlay
Kilo Sage

I'm unable to test this out (as I ended up creating my own UI macro summarizer (read only) based on a script we use to add variables to emails) but commenting out this line prevented the error when saving regular fields on the child form for me. I don't think my client scripts were working on the child form anyway.

<g2:client_script type="catalog_question_editor" catalogItem="$[jvar_catalog_item]"/>

 

ANIL Maddha
Tera Contributor

Hello Guys,

 

First I would like to thank everyone for your suggestions and solutions for the above issues.

 

Did you get a chance to look at the issue related to save/update  variable from task level (Child Task record) . Please suggest any alternative solution to save/update variable from child task record.

 

Thanks,

Anil

rahulpandey
Kilo Sage

Hi All,

This is a very old post of mine and honestly never got a chance to work on this.

I made a very new generic solution for variable editor to work as close as how catalog task editor works.

Below are the steps to use :

- Create a formatter and add UI macro named "CustomVE" in the formatter.

- Add this formatter to your table.

- Create a new system property

 

You are now good to go. This now supports save/update from both child and parent. In this case Incident and incident task.

Note: I did not check this for scoped application. 

You can download this from share https://developer.servicenow.com/connect.do#!/share/contents/3490912_custom_variable_editor_for_reco...

Hopefully this will help all of you.

@ANIL Maddha 

 

Observation : catalog UI policies /  Catalog Client script doesn't work. Workaround : Use table level client script / UI policy client script 

Steve Kelly
Mega Sage

Great work @rahulpandey! Does this new version address the issue with mandatory variables? In the previous version, any variables that are mandatory have to be made mandatory by UI Policy, and not directly on the variable itself, or an error is displayed on save of the child task.

rahulpandey
Kilo Sage

@Steve Kelly 

 

The issue you mentioned doesn't occur anymore

Variable attributes

rahulpandey_2-1686839551195.png

 

Before saving

rahulpandey_0-1686839449939.png

After Saving 

rahulpandey_1-1686839493728.png

It could be due to the old version of UI macro being used earlier.

 

 

rahulpandey
Kilo Sage

@Ashwanth Parine  @Alb1  @Community Alums I know it is too late, but yes saving/updating works now.

rahulpandey
Kilo Sage
ANIL Maddha
Tera Contributor

Great Work @rahulpandey , My requirement is mainly focused on Scoped application. I'll try the solution in scoped app and will confirm.

Thank you very much for your help.

ANIL Maddha
Tera Contributor

@rahulpandey , I'm unable to see your new version of UI macro as I can see Script include in updateset Preview. It would be help if you provide us script of newer version UI macro.

rahulpandey
Kilo Sage

Updateset preview doesn't show UI macros, you need to download it

Logan Poynter
Mega Sage

Great stuff, @rahulpandey! Any suggestions on how I can make this work in a scoped app to save variable changes from the child record? 

ANIL Maddha
Tera Contributor

Hello RahulPandey,

 

Thank you, I have downloaded and followed the same steps which you have mentioned in the article  .

Mandatory Issue, is resolved. I thought I'll work in Scoped application, But unfortunately in not working in scoped application, May be it require few modifications to work for scoped.  

 

I tested this solution for Scoped application, These are my observations.

  • Update/Save functionality is working only for Reference, Select Box and Date fields. Its not working on Single line text, Multi line Text , Check box fields (Test only these 6 Fields).
  • UI policies and Client scripts which were written on Record Producer to apply on Target record are not working on child Task level. 

Really Thank you, great work. Need to see what to do with Scoped app.

 

Thanks and Regards,

Anil

 

Travel Task.PNGTravel Request.PNG

ShrutiKamboj
Tera Contributor

HI @ANIL Maddha 

I have tried your approach. Same issues with me for variable editor variables. Some are not updated. Also, for scoped application do you got the solution? How it will work from Scoped application?

phgdet
Mega Sage
Mega Sage

Hi @ShrutiKamboj , 

To avoid error messages from mandatory fields, switch from checking the Mandatory checkbox directly on the variable record to using a Catalog UI policy. This works for me in a scope application.

phgdet_1-1710828514949.png

phgdet_2-1710828578066.png

 

CrysZzz
Tera Expert

It works for me, thank you so much (~ ̄▽ ̄)~(~ ̄▽ ̄)~(~ ̄▽ ̄)~

Samdavid1
Tera Contributor

Hello Team, this worked really well in the platform. Now in the configurable workspace, since UI macro would not work, the table is not visible. Any ideas to overcome this without touching UI Builder?

 

Thanks in advance

Tim Grindlay
Kilo Sage

@Samdavid1 I haven't worked extensively with workspaces yet but this post seems to suggest that UI formatters still work there. 

Samdavid1
Tera Contributor
Spoiler
Thanks a lot for your response @Tim Grindlay , will definitely check this out
rsdeepakarthiga
Tera Explorer

Hi @rahulpandey  

This solution works in scoped application as well. Thanks a lot!

Only issue is, UI policy is not working in the cascaded task table. Any thoughts?

Kannan Nair
Tera Contributor

@Samdavid1 Please let me know whether you were able to add the variable formatter to the workspace

Todd Goodhew
Tera Expert

Updated solution to more closely match the out-of-box UI macro used for Incident.

NOTES:

When compared to the OOB UI macro for Incident, the following changes were made to get the incident variables to appear on the incident task form view:

  1. Line 14 (current.getUniqueID() was changed to current.incident)
  2. Inserted lines 44-48
<?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:requires name="scripts/js_includes_catalog.js" includes="true"/>
    <g:requires name="styles/${new CatalogCssSelector().getVariableCss()}" includes="true"/>
    <g:if_polaris>
       <g:then>
         <g:requires name="styles/${new CatalogCssSelector().getPolarisVariableCss()}" includes="true"/>
      </g:then>
    </g:if_polaris>
    <g2:evaluate var="jvar_catalog_item">
       function eval_cat_item() {
        var cat_item = "";
		var catItemProducedGr = new GlideRecord("sc_item_produced_record");
		catItemProducedGr.addQuery("record_key", current.incident);
		catItemProducedGr.query();
		if (catItemProducedGr.next())
			cat_item = catItemProducedGr.getValue("producer");
        return cat_item;
       }
       eval_cat_item();
    </g2:evaluate>
	
	<!-- load only the one_to_one variable sets -->
    <g2:evaluate var="jvar_cat_sets" jelly="true">
       var jvar_cat_sets = "";
       var gr = new GlideRecord("io_set_item");
       gr.addQuery("sc_cat_item", jelly.jvar_catalog_item);
	   gr.addQuery("variable_set.type", "one_to_one");
       gr.query();
       while (gr.next()) {
          if (jvar_cat_sets.length > 0)
             jvar_cat_sets += ",";
          jvar_cat_sets += gr.variable_set;
       }
       jvar_cat_sets;
    </g2:evaluate>
	
	<g2:evaluate var="jvar_questionset_read_only" jelly="true">
		(gs.getProperty('glide.sc.evaluate.variables.write.access', true) == 'true') ? !current.variables.canWrite() : !current.canWrite();
	</g2:evaluate>

	<div data-sn-macro-sys-id="${jvar_macro_sys_id}">
		<j2:if test="$[jvar_catalog_item != '']">
			<g2:evaluate jelly="true">
				var recordObject = new GlideRecord('incident');
				recordObject.get(current.incident);
			</g2:evaluate>
			<j2:set var="ref" value="recordObject" />

			<j2:set var="jvar_producer_target_record" value="true"/>
			<g2:client_script type="catalog_question_editor" catalogItem="$[jvar_catalog_item]"/>
			<g:inline template="catalog_ui_policy.xml"/>
			<g2:render_component componentName="com.glideapp.servicecatalog.DefaultQuestionEditor"/>
		</j2:if>
		<j2:if test="$[jvar_catalog_item == '']">
			<!--Render old default editor if catalog item is not found -->
			<g2:render_component componentName="com.glideapp.questionset.DefaultQuestionEditor"/>
		</j2:if>
	</div>
</j:jelly>

 

si21
Tera Guru

Hi everyone,

I have the exact requirement on HR case table.

We have UI action 'Clone case' which creates a record on sn_hr_core_case table and we need the variable editor to be copied to new case.

Has anyone achieved this in scoped application. Please let me know how did you do it.

 

also one observation record key is empty for all records in sc_item_produced_record

catItemProducedGr.addQuery("record_key", current.incident);

TIA

Magda Abu Aitah
Tera Contributor

Hi @Samdavid1 

Did you manage to make the formater appear in Workspace?

Samdavid1
Tera Contributor

Hello @Magda Abu Aitah , no, we had to create custom fields with mapping querying the table "sc_item_option_mtom"

eyal abu hamad
Mega Sage

is it possible to do it for the HR Task table ?
I tried to change some things in ui macro but with no luck

<?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:requires name="scripts/js_includes_catalog.js" includes="true"/>
       <g:requires name="styles/${new CatalogCssSelector().getVariableCss()}" includes="true"/>
<g:requires name="scripts/classes/ServiceCatalogForm.js"/>


<g2:evaluate var="jvar_catalog_item">


             function eval_cat_item() {


               var cat_item = "";


var catItemProducedGr = new GlideRecord("sc_item_produced_record");


catItemProducedGr.addQuery("record_key", current.parent);


catItemProducedGr.query();


if (catItemProducedGr.next())


cat_item = catItemProducedGr.getValue("producer");


               return cat_item;


             }


             eval_cat_item();


       </g2:evaluate>




       <g2:evaluate var="jvar_cat_sets" jelly="true">


             var jvar_cat_sets = "";


             var gr = new GlideRecord("io_set_item");


             gr.addQuery("sc_cat_item", jelly.jvar_catalog_item);


             gr.query();


             while (gr.next()) {


                   if (jvar_cat_sets.length > 0)


                         jvar_cat_sets += ",";


                   jvar_cat_sets += gr.variable_set;


             }


             jvar_cat_sets;


       </g2:evaluate>




<div data-sn-macro-sys-id="${jvar_macro_sys_id}">


<g2:evaluate jelly="true"> var recordObject = new GlideRecord('sn_hr_core_task');


recordObject.get(current.parent);


</g2:evaluate>


<j2:set var="ref" value="recordObject" />


<j:set var="jvar_producer_target_record" value="true"/>


<g2:client_script type="catalog_item" catalogItem="$[jvar_catalog_item]"/>

<g:inline template="catalog_ui_policy.xml"/>

<g2:render_component componentName="com.glideapp.servicecatalog.DefaultQuestionEditor"/>


</div>


</j:jelly>
benjaminganjr
Tera Explorer

Many Thanks @rahulpandey for the solutions,  👍

And for an update for the UI policy that is not executing on the child case I just reallocate and update a little to the code in the CustomVE [macro] and place it at the bottom part somewhere LINE 41 (after the 

<g2:evaluate var="jvar_questionset_read_only" jelly="true"> ). 

Hope this help 😉
 
<div data-sn-macro-sys-id="${jvar_macro_sys_id}">
		<j2:if test="$[jvar_catalog_item != '']">

		      <g2:evaluate jelly="true"> 
			  var recordObject = new GlideRecord('incident');
                  recordObject.get(current.parent.sys_id);
              </g2:evaluate>
              <j2:set var="ref" value="recordObject" />

			<j2:set var="jvar_producer_target_record" value="true"/>
			<g2:client_script type="catalog_question_editor" catalogItem="$[jvar_catalog_item]"/>
			<g:inline template="catalog_ui_policy.xml"/>
			<g2:render_component componentName="com.glideapp.servicecatalog.DefaultQuestionEditor"/>
		</j2:if>
		<j2:if test="$[jvar_catalog_item == '']">
			<!--Render old default editor if catalog item is not found -->
			<g2:render_component componentName="com.glideapp.questionset.DefaultQuestionEditor"/>
		</j2:if>
	</div>



	<g2:evaluate var="jvar_VEProp" object="true">
var variableEditorObject = {};
var defaultProperty = gs.getProperty("customve.default.parent.field");
var tablePropName = "customve."+current.sys_class_name.toString()+".parent.field"
var tableLevelProperty = gs.getProperty(tablePropName);


if(JSUtil.notNil(tableLevelProperty)){
	variableEditorObject.parent = current[tableLevelProperty]["sys_class_name"];
	variableEditorObject.parentrecordid = current[tableLevelProperty];
}
else if(JSUtil.notNil(defaultProperty)){
variableEditorObject.parent = current[defaultProperty]["sys_class_name"];
variableEditorObject.parentrecordid = current[defaultProperty];
}
variableEditorObject;
</g2:evaluate>



		<!-- Get All variables fields from parent table -->
	<g2:evaluate var="jvar_catalog_fields" jelly="true">
		function getProducerID(parentTable, parentrecordid){
			getcatid = new GlideRecord("question_answer");
			getcatid.addEncodedQuery("table_name="+parentTable+"^table_sys_id="+parentrecordid);
			getcatid.setLimit(1);
			getcatid.query();
			if(getcatid.next())
			return getcatid.question.cat_item;
		}
		var catitem = getProducerID(jelly.jvar_VEProp.parent, jelly.jvar_VEProp.parentrecordid);
var variablesArray= [];
	var getVariables = new GlideRecord("item_option_new");
		getVariables.addEncodedQuery("active=true^cat_item="+catitem);
		getVariables.query();
		while(getVariables.next()){
			variablesArray.push(getVariables.getValue("name"));
		}
		variablesArray;
	</g2:evaluate>

	

		<script>
	/* <![CDATA[ */
CustomEvent.observe("glideform.submit_attempted", function(){
	var allVariables = "$[jvar_catalog_fields]";
	allVariables = allVariables.split(",");
var VariablesWithValuesObject = {};
for(var i =0; i &lt; allVariables.length; i++){
	var fieldName = allVariables[i];
	var fieldValue = g_form.getValue(allVariables[i]);
	if(fieldValue)
	VariablesWithValuesObject[fieldName] = fieldValue;

}
var ga = new GlideAjax('customVEUtils') ;
ga.addParam('sysparm_name','updateVariables');
ga.addParam('sysparm_fnv',JSON.stringify(VariablesWithValuesObject));
ga.addParam('sysparm_tableName','$[jvar_VEProp.parent]');
ga.addParam('sysparm_recordid','$[jvar_VEProp.parentrecordid]');
ga.getXMLWait(); 
<!-- used getXMLWait so the update can finish before page load -->

});
/* ]]> */
	</script>
	

</j:jelly>​




bhushannerkar
Tera Expert

Hello @rahulpandey @benjaminganjr and all other Community members,

I created a custom macro to load the variable editor formatter for a Record Producer on the Task table (for custom application). The macro is almost working fine — UI Policies and onLoad Client Scripts are working — but onChange Catalog Client Scripts are not triggering.

I followed this post while building it.

Has anyone faced this issue or can provide guidance on how to get onChange Client Scripts working?

Any help will be appreciated.

Thanks.

CC: @Ankur Bawiskar   @Dr Atul G- LNG    @Ravi Gaurav  @Pradeep Sharma  @Chuck Tomasi  @Brad Bowman 

 

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
    <!-- Load required scripts and styles -->
    <g:requires name="scripts/js_includes_catalog.js" includes="true" />
    <g:requires name="styles/${new CatalogCssSelector().getVariableCss()}" includes="true" />
    <g:if_polaris>
        <g:then>
            <g:requires name="styles/${new CatalogCssSelector().getPolarisVariableCss()}" includes="true" />
        </g:then>
    </g:if_polaris>
    <!-- Evaluate parent record and catalog item details -->
    <g2:evaluate var="jvar_VEProp" object="true">
        var variableEditorObject = {};
        var defaultProperty = gs.getProperty("customve.default.parent.field");
        var tablePropName = "customve."+current.sys_class_name.toString()+".parent.field";
        var tableLevelProperty = gs.getProperty(tablePropName);
        if(JSUtil.notNil(tableLevelProperty)){
        variableEditorObject.parent = current[tableLevelProperty]["sys_class_name"];
        variableEditorObject.parentrecordid = current[tableLevelProperty];
        } else if(JSUtil.notNil(defaultProperty)){
        variableEditorObject.parent = current[defaultProperty]["sys_class_name"];
        variableEditorObject.parentrecordid = current[defaultProperty];
        }
        variableEditorObject;
    </g2:evaluate>
    <g2:evaluate var="jvar_catalog_item" jelly="true">
        function eval_cat_item() {
        var cat_item = "";
        var catItemProducedGr = new GlideRecord("sc_item_produced_record");
        catItemProducedGr.addQuery("record_key", jelly.jvar_VEProp.parentrecordid);
        catItemProducedGr.query();
        if (catItemProducedGr.next())
        cat_item = catItemProducedGr.getValue("producer");
        return cat_item;
        }
        eval_cat_item();
    </g2:evaluate>
    <p>jvar_catalog_item: $[jvar_catalog_item]</p>
    <!-- NEW G2 EVALUATE TO GET THE PARENT RITM ID -->
    <g2:evaluate var="jvar_parent_ritm_id" jelly="true">
        var parent_ritm = '';
        if (jelly.current.getRecordClassName() === current.getRecordClassName() &amp;&amp; jelly.current.request_item.getRefRecord().isValid()) {
        parent_ritm = jelly.current.request_item;
        }
        <!-- 2nd way -->
        <!-- if (jelly.current.getRecordClassName() === current.getRecordClassName() &amp;&amp; JSUtil.notNil(jelly.current.request_item)) {
        parent_ritm = jelly.current.request_item;
        } -->
        <!-- var currentTaskGr = new GlideRecord(current.getRecordClassName());
        if (currentTaskGr.get(current.getUniqueValue())) {
        parent_ritm = currentTaskGr.getValue('request_item');
        } -->
        parent_ritm;
    </g2:evaluate>
    <p>jvar_parent_ritm_id: $[jvar_parent_ritm_id]</p>
    <!-- <p> jelly.current.getUniqueValue() : $[jelly.current.getUniqueValue()] </p> -->
    <j2:set var="jvar_producerName" value="$[jvar_catalog_item]" />
    <p>jvar_producerName: $[jvar_producerName]</p>
    <!-- Get all active variables (including SRVS and MRVS) from the producer -->
    <g2:evaluate var="jvar_catalog_fields" jelly="true">
        function getProducerID(parentTable, parentrecordid) {
        var catitem = "";
        var getcatid = new GlideRecord("question_answer");
        getcatid.addEncodedQuery("table_name=" + parentTable + "^table_sys_id=" + parentrecordid);
        getcatid.setLimit(1);
        getcatid.query();
        if (getcatid.next())
        catitem = getcatid.question.cat_item;
        return catitem;
        }
        var catitem = getProducerID(jelly.jvar_VEProp.parent, jelly.jvar_VEProp.parentrecordid);
        var variablesArray = [];
        // Get top-level variables and variables from all variable sets
        var getVariables = new GlideRecord("item_option_new");
        var encodedQuery = "active=true^cat_item=" + catitem + "^ORvariable_set.sc_cat_item=" + catitem;
        getVariables.addEncodedQuery(encodedQuery);
        getVariables.query();
        while (getVariables.next()) {
        variablesArray.push(getVariables.getValue("name"));
        }
        variablesArray;
    </g2:evaluate>
    <g2:evaluate var="jvar_questionset_read_only" jelly="true">
        (gs.getProperty('glide.sc.evaluate.variables.write.access', true) == 'true') ? !current.variables.canWrite() : !current.canWrite();
        false;
    </g2:evaluate>
    <div id="variable_editor_container" data-sn-macro-sys-id="${jvar_macro_sys_id}">
        <g2:evaluate jelly="true">
            var recordObject = new GlideRecord(jelly.jvar_VEProp.parent);
            recordObject.get(jelly.jvar_VEProp.parentrecordid);
        </g2:evaluate>
        <j2:set var="ref" value="recordObject" />
        <j2:if test="$[jvar_catalog_item != '']">
            <j2:set var="jvar_producer_target_record" value="true" />
			<!-- triggering onload client script -->
            <g2:client_script type="catalog_question_editor" catalogItem="$[jvar_catalog_item]"  />
            <!-- NEW CODE TO LOAD CLIENT SCRIPTS FROM THE PARENT RITM -->
            <j2:if test="$[jvar_parent_ritm_id != '']">
                <g2:client_script type="catalog_question_editor" recordId="$[jvar_parent_ritm_id]" />
                <!-- <g2:client_script type="catalog_question_editor" recordId="$[jvar_parent_ritm_id]" /> -->
            </j2:if>
            <p>jvar_parent_ritm_id: $[jvar_parent_ritm_id]</p>
            <!-- <g:inline template="catalog_client_scripts.xml" /> -->
            <!-- <g:inline template="catalog_ui_policy_script.xml" /> -->
            <g:inline template="catalog_ui_policy.xml" />
            <g2:render_component componentName="com.glideapp.servicecatalog.DefaultQuestionEditor" />
        </j2:if>
        <j2:if test="$[jvar_catalog_item == '']">
            <!--Render old default editor if catalog item is not found -->
            <g2:render_component componentName="com.glideapp.questionset.DefaultQuestionEditor" />
        </j2:if>
    </div>
    <script>
        /* <![CDATA[ */
        // This is the client-side script that runs when the form is submitted
        CustomEvent.observe("glideform.submit_attempted", function() {
            var allVariables = "$[jvar_catalog_fields]";
            allVariables = allVariables.split(",");
            var VariablesWithValuesObject = {};

            // Loop through all variables and get their values directly
            for (var i = 0; i &lt; allVariables.length; i++) {
                var fieldName = allVariables[i];
                var fieldValue = g_form.getValue(fieldName);

                if (fieldValue) {
                    VariablesWithValuesObject[fieldName] = fieldValue;
                }
            }

            // Call the Script Include to update variables on the parent record asynchronously
            var ga = new GlideAjax('customVEUtils');
            ga.addParam('sysparm_name', 'updateVariables');
            ga.addParam('sysparm_fnv', JSON.stringify(VariablesWithValuesObject));
            ga.addParam('sysparm_tableName', '$[jvar_VEProp.parent]');
            ga.addParam('sysparm_recordid', '$[jvar_VEProp.parentrecordid]');
            ga.getXML(function(response) {
                console.log('Variables updated successfully.');
            });
        });

        // This function ensures UI policies and client scripts run on page load
        addLateLoadEvent(function() {
            var allVariables = "$[jvar_catalog_fields]";
            var variableNames = allVariables.split(",");
            if (variableNames.length === 0) {
                return;
            }

            const checkInterval = setInterval(function() {
                // Check if the first variable's control element is available
                if (g_form.getControl(variableNames[0])) {
                    // Manually trigger a change event on all variables to force UI policy re-evaluation
                    for (var i = 0; i &lt; variableNames.length; i++) {
                        var varName = variableNames[i];
                        // Fire a change event, which is a more explicit way to trigger an onChange script
                        g_form.fireEvent('change', varName);
                    }

                    // As an added layer of certainty, also call applyUIPolicies
                    g_form.applyUIPolicies();

                    // Clear the interval once we've successfully applied the policies
                    clearInterval(checkInterval);
                }
            }, 100); // Check every 100ms
        });
        /* ]]> */
    </script>
</j:jelly>
Dr Atul G- LNG
Tera Patron
Tera Patron

sorry @bhushannerkar  coding is not my best area.

Ankur Bawiskar
Tera Patron
Tera Patron

@bhushannerkar 

Please post this as a question and share all the details there and tag.

This is a post/article.

benjaminganjr
Tera Explorer

Hello @bhushannerkar 
 

May we know your purpose why you need it in OnChange rather than Onload?

bhushannerkar
Tera Expert

Hello @benjaminganjr ,

I want to replicate behavior like on change of any field, update another field value.

Sameer Fayaz1
Tera Contributor

This is a helpful article. Thanks for posting it.

Version history
Last update:
‎12-12-2020 11:44 AM
Updated by: