appy New Year! Hopefully everybody had a great holiday. Mine was spent mostly helping my kids to break in some new toys :). I did get some time to play with some new Service-now ideas as well. I’ll be sharing some very cool stuff here on SNCGuru over the next couple of weeks.
I’ve seen a couple requests recently for a way to allow users to select items from a slushbucket popup dialog. The most common reason for this is to help manage manual group approvals on a task record. If you’ve worked with group approvals at all, you’ve probably noticed that they work a little bit differently than regular approval records do. Group approval records are really just task records so you can’t just hit an ‘Edit’ button and add groups to be approvers on a task. Instead, you have to repeatedly click the ‘New’ button and create a new task record for each approval group. Normally this isn’t an issue because group approvals are typically managed in workflow but if you’re manually adding a lot of these, the process can be fairly tedious.
This article shows how you can provide a better UI by creating a slushbucket popup dialog that allows users to select one or many groups to add as approvers on a task. Even though the solution is designed for a specific use case, I’ve tried to make the example shown here generic enough so that you can easily modify it for other uses as well.

The first piece to this solution is to create a trigger for the dialog. For this solution, a UI action probably makes the most sense. The end user will click a UI action to display the popup dialog and make the necessary selections there.

‘Add Approval Groups’ UI Action
Name: Add Approval Groups
Client: true
Form link: true
OnClick: addApprovalGroups()
Condition: gs.hasRole(‘itil’)

function addApprovalGroups(){
   //Open a dialog window to select Approval Groups
   var dialog = new GlideDialogWindow('add_approval_groups');
   dialog.setTitle('Add Approval Groups');
   dialog.setPreference('sysparm_groupQuery', 'active=true');
   //Make sure to not submit the form when button gets clicked
   return false;

The UI action opens the dialog with a call to a specific UI page. The UI page is what contains most of the logic for the slushbucket. It includes the actual HTML (which pulls in the slushbucket and UI buttons from UI macros) as well as the client script that loads the groups and makes a call to insert group approval records.

‘add_approval_groups’ UI Page
Name: add_approval_groups

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
            Please select the groups you wish to add as approvers.
            <!-- Include the 'ui_slushbucket' UI macro -->
         <TD align="right">
            <!-- Include the 'dialog_buttons_ok_cancel' UI macro -->
            <g:dialog_buttons_ok_cancel ok="return continueOK()" cancel="return continueCancel()" ok_type="button" cancel_type="button"/>

Client script:

//Called when the 'OK' button gets clicked
function continueOK(){
   //Get the selected values from the right slushbucket
   var values = slush.getValues(slush.getRightSelect());
   //Get the sys_id of the current record
   var taskID = g_form.getUniqueValue();
   //Make sure we have at least one selection
   if(values == ''){
      alert("At least one group must be selected");

   //Add the group approval records
   var ajax = new GlideAjax('GroupSelectAjax');
   ajax.addParam('sysparm_name', 'groupsAdd');
   ajax.addParam('sysparm_taskID', taskID);
   ajax.addParam('sysparm_values', values);

//Called when we get a response from the 'continueOK' function
function addGroupResponse(){
   return false;

//Called when the 'Cancel' button gets clicked
function continueCancel(){
   //Close the dialog window
   return false;

//Called when the form loads
   //Load the groups when the form loads
   var ajax = new GlideAjax('GroupSelectAjax');
   ajax.addParam('sysparm_name', 'getGroups');
   return false;

//Called when we get a response from the 'addLoadEvent' function
function loadResponse(response){
   //Process the return XML document and add groups to the left select
   var xml = response.responseXML;
   var e = xml.documentElement;

   var items = xml.getElementsByTagName("item");
   if(items.length == 0)

   //Loop through item elements and add each item to left slushbucket
   for (var i = 0; i < items.length; i++) {
      var item = items[i];
      slush.addLeftChoice(item.getAttribute('value'), item.getAttribute('text'));

Many times, you can stop with the UI page. In this case, it makes sense for us to do some of our heavy-lifting for populating the groups in the slushbucket and creating group approval records at the server. The client scripts in the UI page make GlideAjax calls to the functions in a script include. The script include performs the query and returns an XML response back to the client so that it can continue.

‘GroupSelectAjax’ Script Include
Name: GroupSelectAjax
Client callable: true

var GroupSelectAjax = Class.create();

GroupSelectAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
   //Get and return a list of groups (name and sys_id)
   getGroups: function() {  
      var gr = new GlideRecord("sys_user_group");
      gr.addQuery('active', true);  

      //Add the available groups to select from
      while (gr.next()) {
         var item = this.newItem();
         item.setAttribute('value', gr.getValue('sys_id'));
         item.setAttribute('text', gr.getValue('name'));

   //Take a taskID and group sys_id values and add 'sysapproval_group' records
   groupsAdd: function() {
      var taskID = this.getParameter('sysparm_taskID');
      var values = this.getParameter('sysparm_values').split(',');
      //Iterate through the group sys_id values
      for(x in values){
         var rec = new GlideRecord('sysapproval_group');
         rec.parent = taskID;
         rec.assignment_group = values[x];
         rec.approval = 'requested';