- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-24-2021 08:06 AM
Hello all,
We have a requirement to create a copy button for requests/requested items in the Service Portal to be used to copy closed requests so the user does not have to enter the same information into a new request. I have been researching what others have done, and have found:
1.It is suggested that there is already one OOB, however I do not find one in my personal dev instance when following the directions in How to make Copy button form expose on service portal?.
2. I have also found Button to copy and insert a new ticket into table, but it is specific to incidents and I am not sure how to adapt it to requests, which have variables that can vary widely.
3. I also took at look at the UI action on Requests in the platform, which I thought might serve as a template for creating a widget, but I am not sure if it would work:
var helper = new GlideappScriptHelper();
var request = helper.copyRequest(current);
gs.addInfoMessage(gs.getMessage('Request copied successfully'));
action.openGlideRecord(request);
Has anyone done this before, or can someone assist with how I might do this? Is it possible to adapt 2. or 3. above to my purpose or can someone point me in the right direction for finding the OOB copy button from 1. above?
Any help will be appreciated. Thanks!
Solved! Go to Solution.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-24-2021 08:22 AM
Ok so yeah its like this widget to resubmit request on the ticket page, script include to build the URL, variable set called 'copy_variables_from_uri_ritm_id' with client script to parse the URL
Widget HTML:
<div ng-if="::c.data.show_button" class="panel panel-default b wrapper-md" ng-class="{'wrapper-md': options.native_mobile != 'true', 'wrapper-sm': options.native_mobile == 'true'}">
<button name="resubmit" ng-disabled="c.resubmitting" ng-click="c.redirectToResubmit()" class="btn btn-primary btn-block ng-binding ng-scope">
Resubmit Request
</button>
</div>
Widget Client script:
function() {
var c = this;
c.resubmitting = false;
c.redirectToResubmit = function() {
c.resubmitting = true;
c.server.get({
resubmitting: true
}).then(function(r) {
top.window.location = r.data.resubmit_url;
});
}
}
Widget Server script:
(function() {
var tableName = $sp.getParameter('table');
var recordId = $sp.getParameter('sys_id');
if(tableName && recordId) {
var recordGr = new GlideRecord(tableName);
recordGr.get(recordId);
if(!input) {
data.show_button = new CatalogVariableURLBuilder().hasVariableSet(recordGr, 'copy_variables_from_uri_ritm_id');
}
}
if(input && input.resubmitting) {
data.resubmit_url = new CatalogVariableURLBuilder().getResubmitURL('sc_cat_item', recordGr);
}
})();
CatalogVariableURLBuilder script include:
var CatalogVariableURLBuilder = Class.create();
CatalogVariableURLBuilder.prototype = {
initialize: function() {},
getJsonFromGr: function(ritmGr) {
var variablesObj = ritmGr.variables.getElements(false);
var outputObj = {};
for (var i = 0; i < variablesObj.length; ++i) {
var variable = variablesObj[i];
var question = variable.getQuestion();
if (question.getValue() && question.getName()) {
outputObj[question.getName()] = question.getValue();
}
}
return JSON.stringify(outputObj);
},
hasVariableSet: function(ritmGr, variableSetName) {
if(ritmGr.getTableName() != 'sc_req_item' || !ritmGr.getValue('cat_item')) {
return false;
}
var ioSetItem = new GlideRecord('io_set_item');
ioSetItem.addQuery('sc_cat_item', ritmGr.getValue('cat_item'));
ioSetItem.addQuery('variable_set.internal_name', variableSetName);
ioSetItem.query();
return ioSetItem.hasNext();
},
getResubmitURL: function(catItemPageId, ritmGr) {
var catItemSysId = ritmGr.cat_item.toString();
return "?id=" + catItemPageId + "&sys_id=" + catItemSysId + "&sysparm_copy_from_ritm_id=" + ritmGr.getUniqueValue();
},
type: 'CatalogVariableURLBuilder'
};
Variable set:
Onload client script (in this variable set)
function onLoad() {
var prop, propVal;
//get parameter from URL
var ritmId = getParameterValue('sysparm_copy_from_ritm_id');
console.debug('sysparm_variables URI parameter value: ' + ritmId);
if (!ritmId) {
//If parameter is empty, stop here.
console.debug('aborting due to a missing sysparm_copy_from_ritm_id URI parameter');
return;
}
var getVariableJson = new GlideAjax('CopyVariablesAjax');
getVariableJson.addParam('sysparm_name', 'getVariableJson');
getVariableJson.addParam('sysparm_copy_from_ritm_id', ritmId);
getVariableJson.getXMLAnswer(populateForm);
function populateForm(variableJsonStr) {
console.debug('sysparm_copy_from_ritm_id variables JSON object: ' + variableJsonStr);
var variableJson = JSON.parse(variableJsonStr);
for(var formVariable in variableJson) {
if(g_form.hasField(formVariable)) {
g_form.setValue(formVariable, variableJson[formVariable]);
}
}
}
}
function getParameterValue(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
//Check if portal (gel=undefined) or classic UI, and get the HREF data appropriately in either case.
var hrefPath = (typeof gel == 'undefined') ? this.location.href : top.location.href;
var results = regex.exec(hrefPath);
console.debug('HREF: ' + hrefPath);
if (results == null) {
return "";
} else {
return unescape(results[1]);
}
}
CopyVariablesAjax script include client callable:
var CopyVariablesAjax = Class.create();
CopyVariablesAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getVariableJson: function() {
var ritmId = this.getParameter('sysparm_copy_from_ritm_id');
var ritm = new GlideRecord('sc_req_item');
if(!ritm.get(ritmId)) {
return "{}";
}
return new CatalogVariableURLBuilder().getJsonFromGr(ritm);
},
type: 'CopyVariablesAjax'
});
Ok now you just need to, add the variable set to any catalog item that you want this functionality to work in, and also you should add the widget to the ticket page where the button needs to be.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-24-2021 12:59 PM
Ah yes sorry about that I didn't read your requirement well enough but good catch with state == '3'.
That's strange I'm not able to reproduce that issue in my instance with date variables, even with different date formats. Just to clarify are these date variables or date/time? It's possible it's a time zone issue with date/time as the Ajax is probably going to send date/times back in the UTC time zone. Let me know if that's the case and I'll see if I can reproduce or fix the issue.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-25-2021 04:04 AM
Hmmm...they are just date variables.
The time zone idea might be valid though. I also thought about caching, but I get the same result in an incognito window.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-25-2021 06:41 AM
So I figured out why the date was showing the day before, although it doesn't make a lot of sense to me. I had to change my date setting, which is personally configurable in my profile, to match the system date configuration. This might be a bit of a problem since the user can choose their date format themselves...It also fixed the problem with the date validation script. Thanks a lot for your help with this!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-07-2023 08:24 AM - edited ‎07-12-2023 06:28 AM
is there is any possibility to not having Variable set added to Catalogs and achieve this? because it will become a mandatory task when we build new catalog, so we need to add it and having added VSet to all catalogs also customer agreeing. Please suggest.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-10-2023 03:13 AM
is there is any possibility to not having Variable set added to Catalogs and achieve this? because it will become a mandatory task when we build new catalog, so we need to add it and having added VSet to all catalogs also customer agreeing. Please suggest.