- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 03-29-2019 06:15 AM
Evening Everyone
Ive been working on the problem of UI Macro's in Catalog Variables.
While seemingly powerful, they are hindered by their abject lack, apparently, of storage capacity outside workarounds like storing data in other variables via onSubmit or onChange client scripts to get the data SOMEWHERE to use, plus the added challenge of bringing the data back on next load to use again.
In looking into this I confirmed a few things
- The macro variable CAN store data at a table level. Its just a normal sc_item_option record linked to the parent RITM via a sc_item_option_mtom record. Nothing fancy
- If we manually put data in that record, we CAN read it back using the automatically available ${jvar_question_value} Phase 1 jelly variable
- We CAN identify the macro variable as unique by using the ${jvar_question_name} variable
-
- This variable is made up of the text ni.VE plus the sys_id of the sc_item_option record
- We CANNOT update that variable or retrieve data from that variable using standard g_form or g_sc_form methods
So that left one option I could see, find a way to update the sc_item_option value through a processor on the form being submitted, exactly how the normal form backend works.
There was one blocker and one personal preference in the way
- Blocker: We cant run server side code off the submit (ok thats not exactly true, but for simplicity's sake and the next reason, it is)
- Preference: We cant slow down the process of saving the record in any significant way.
So without further ado, here's what I ended up with
Its a two part process, on the server side we are passing the sys_id of the sc_item_option record, along with the value to save to an Ajax endpoint
var vCatalogMacroUtils = Class.create();
vCatalogMacroUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
setMacroValue: function(){
var value = this.getParameter('sysparm_value');
var element = this.getParameter('sysparm_element');
gs.log("TESTING: " + value + " / " + element);
var sc = new GlideRecord('sc_item_option');
if(sc.get(element)){
sc.value = value;
sc.update();
}
},
type: 'vCatalogMacroUtils'
});
In the macro, we are invoking this by binding a onSubmit event using the form available addOnSubmitEvent method
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="true" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<j:set var="jvar_data" value="${jvar_question_value}" />
<j:set var="jvar_control_name" value="${jvar_question_name.replace('ni.VE', '')}" />
<j:set var="jvar_record_id" value="${RP.getParameterValue('sys_id')}" />
<input id="macro_value_${jvar_control_name}" value="${jvar_data}" /><br />
<script>
$j('document').ready(function(){
if (addOnSubmitEvent) {
var form${jvar_control_name} = g_form.getFormElement();
if (form${jvar_control_name}) {
console.log("testing addSubmit");
addOnSubmitEvent(form${jvar_control_name}, setValueInBackend${jvar_control_name});
}
}
});
function setValueInBackend${jvar_control_name}(){
var ajax${jvar_control_name} = new GlideAjax('vCatalogMacroUtils');
ajax${jvar_control_name}.addParam('sysparm_name', 'setMacroValue');
ajax${jvar_control_name}.addParam('sysparm_value', gel('macro_value_${jvar_control_name}').value);
ajax${jvar_control_name}.addParam('sysparm_element', '${jvar_control_name}');
ajax${jvar_control_name}.getXML();
}
</script>
</j:jelly>
The ajax side is simple, take value and id, retreive using GlideRecord and update.
On the client side, its a bit more messy. To explain
(note all the ${jvar_control_name} values are to ensure multiple copies of the same macro dont collide with each other)
We start of by grabbing the values we need to run the process (the j:set lines)
The sample above is a single text field, obviously not super useful but enough for testing purposes
We then do an ready check (using jquery for laziness really 😉 ), then bind a function to handle the onSubmit.
The function simply calls the Ajax method using the previously stored variable element id (jvar_control_name) and gel's the value of the input field.
We then fire the Ajax asynchronously, but with no callback because we arent postprocessing anything.
The result. On form reload, the variable has updated!!!!!!!!!!!!!!!
And the big big test, checking the value using current.variables.variable_name gives us our save data.
Id love some feedback on this solution.
As is its a simple sample, but the options here could be as powerful as you can think of. Eg we could take a block of JSON data, parse it, load it into a complex and editable table using a library such as DataTables, let the user interact, add, edit, sort, change etc, then onSubmit we take the new data back to a JSON string and put it back where it came from (or so help me).
And all without adding extra client scripts for every new variable, macro or usage!
- 1,580 Views