UI Action For Copying Selected Records

tomopl
Kilo Contributor

Hi there,

I need functionality as follows. On the list view of my custom task table, I want to have an extra option on the bottom of choice list that copies selected items X number of times, where X is numeric value that user inputs in a popup window. Sounds not complicated. I made a new UI Action that is located in list choice. I have a code:

function copyItems() {

  selSysIds = g_list.getChecked();

      sysIdList = selSysIds.split(',');

  var con = prompt("How many times copy selected records? (" + sysIdList.length + " selected)");

      if(some validation if it's a number whatever) {

            something

      }

      else{

    return false;

      }

}

And that is working nicely. I get the popup window, I can retrieve number from the popup, I can retrieve selected sys IDs. What I don't know, is how I could insert a new record (my actual copying functionality - I would just copy field by field from one ticket to other place) to another table. The "Client" checkbox is selected because that is the only way I have access to g_list and prompt popup. When "Client" is selected I don't have access to server side functions though (glide record etc.).

I know I can access both server and client methods in UI Action by using something like this (found in the default UI Actions in SN):

function callableFromUIAction(){

    //Call the UI Action and skip the 'onclick' function

    gsftSubmit(null, g_form.getFormElement(), 'action_name'); //MUST call the 'Action name' set in this UI Action

}

//Code that runs without 'onclick'

//Ensure call to server-side function with no browser errors

if(typeof window == 'undefined')

    someFunction();

function someFunction(){

        something

}

But that wouldn't work because I need to pass the number of records to copy from the prompt. AFAIK it is impossible. And secondly - I tried to work with this and it wouldn't work for me when called on the list view.

Anyone has an idea how I should implement this functionality? I tried calling a script include, it stopped the script on creating new GlideRecord. I'm using an application scope. Either in this way (preferably) or with another method (I guess I could add an extra 2 fields in my form like "Enter ticket numbers to copy" and "How many times to copy that record" and where those 2 are filled in, just copy them and ignore the default insert / update on a record). But that's a quite big workaround and it's not exactly what I want.

2 REPLIES 2

Michael Ritchie
ServiceNow Employee
ServiceNow Employee

To copy the records all you really need to do it loop through the list, query for each GlideRecord and do an insert on each, that will change the sys_id of each.   I would suggest clearing out the number, state, and other fields you need to make unique to this new record.



You are in the right track to make this happen server side.   You can use GlideAjax to send the list and count to an Ajax script include to then process.   There are articles on the Wiki on GlideAjax.



The SN Nerd
Giga Sage
Giga Sage

Take a look at the OOB Delete UI Action as an example of how to do this.



UI Action (List Choice, Client Side) calls confirmAndDeleteFromList()  


var tblName;


var ajaxHelper;


var selSysIds;


var sysIdList;


var indx = 0;


var numSel = 0;




function confirmAndDeleteFromList() {


      tblName = g_list.getTableName();


      selSysIds = g_list.getChecked();


      sysIdList = selSysIds.split(',');


      numSel = sysIdList.length;


   


      if(numSel > 0) {


              indx = 0;


              ajaxHelper = new GlideAjax('DeleteRecordAjax');


              getCascadeDeleteTables();


      }


}




function getCascadeDeleteTables() {


      if(sysIdList[indx] != '') {


              ajaxHelper.addParam('sysparm_name', 'getCascadeDeleteTables');


              ajaxHelper.addParam('sysparm_obj_id',sysIdList[indx]);


              ajaxHelper.addParam('sysparm_table_name', tblName);


              ajaxHelper.addParam('sysparm_nameofstack', null);


              ajaxHelper.getXMLAnswer(getCascadeDelTablesDoneList.bind(this), null, null);


      }


}




function getCascadeDelTablesDoneList(answer, s) {


      var delObjList = '';


      var selObjName = '';




      if(answer != '') {    


              var ansrArray = answer.split(';');


              if(ansrArray.length > 1) selObjName = ansrArray[1];


              if(ansrArray.length > 2) delObjList = ansrArray[2];


      }


   


      if(delObjList != '') {


  if(numSel > 1) {


                      showListConfDlg("true", selObjName, delObjList);


              } else {


      showListConfDlg("true" , '', delObjList);


  }




      } else {


      indx++;


              if(indx < numSel) {


                      ajaxHelper.addParam('sysparm_name', 'getCascadeDeleteTables');


                      ajaxHelper.addParam('sysparm_table_name', tblName);


      ajaxHelper.addParam('sysparm_obj_id', sysIdList[indx]);


      ajaxHelper.getXMLAnswer(getCascadeDelTablesDoneList.bind(this), null, null);


  } else {


      showListConfDlg("false", '');


  }


      }


}




function showListConfDlg(hasCascadeDel, selObjName, delObjList) {


  var dialogClass = typeof GlideModal != 'undefined' ? GlideModal : GlideDialogWindow;


      var dlg = new dialogClass('delete_confirm_list');


      dlg.setTitle('Confirmation');


      if(delObjList == null) {


              dlg.setWidth(300);


      } else {


              dlg.setWidth(450);


      }


   


      dlg.setPreference('sysparm_obj_list', selSysIds);


      dlg.setPreference('sysparm_table_name', tblName);


      dlg.setPreference('sysparm_has_cascade_del', hasCascadeDel);


      dlg.setPreference('sysparm_sel_obj_name', selObjName);


      dlg.setPreference('sysparm_del_obj_list', delObjList);


      dlg.render();


}



Script Include "DeleteRecordAjax"


  getCascadeDeleteTables: function() {


          var confNeeded = gs.getProperty('glide.ui.confirm_cascade_delete');


          if(confNeeded == null || confNeeded != "true") {


                return '';


          }


          var objSysId = this.getParameter('sysparm_obj_id');


          var tblName = this.getParameter('sysparm_table_name');


          var stackName = this.getParameter('sysparm_nameofstack');


    var gotoUrl = this.getParameter('sysparm_goto_url');


         


          var dMap = GlideCascadeFromDelete.getCascadeTables(tblName, objSysId, stackName);


          var retUrl = dMap.remove("return_url");




          // Use the more explicit sysparm_goto_url if it exists


          if (gotoUrl && gotoUrl != "")


                  retUrl = gotoUrl;


     


          var dList = '';


          if(retUrl != null) dList += retUrl + ';';


                else dList += 'null;';


               


          if( dMap.isEmpty()) {


                return dList;


          }


         


          // translate returned Java Map to a string format that client page can understand


          var objName = dMap.remove("name");


          dList += objName + ';';


          var itr = dMap.keySet().iterator();


          while(itr.hasNext()) {


                var dTbl = itr.next();


                var count = dMap.get(dTbl).intValue();


                dList = dList + count + ':' + dTbl + ',';


          }


          return dList;


    },



ServiceNow Nerd
ServiceNow Developer MVP 2020-2022
ServiceNow Community MVP 2019-2022