How to create a filterable list popup via a UI Page

Racine1
Tera Contributor

I recently was faced with a challenge on how to bulk add multiple users from a dialog box. It is similar to if you click the Edit button but in my use case I needed to show a list of users when sys_user was not the table being referenced. I achieved it by created a Table and Condition field on a custom form and then created a UI Page and Script include. You can find the code below.

 

Code to call the UI Page from a UI Action

function onClickFunctionName(){
   
   var dialog = new GlideDialogWindow('slush_bucket_users');
   dialog.setTitle('Add Users');
   dialog.setSize(1000,500);
   dialog.render();
   return false;
}

 

UI Page HTML

<?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:evaluate jelly="true"></g:evaluate>
  <g:requires name="elements/element_conditions.jsx"></g:requires>
  <TABLE BORDER="0">
    <TR>
      <TD>
        <div>Conditions</div>
		  <!-- you need a table name field and a condition field that is dependent on that table name field here. You can use any table with those two fields but make sure there are no tableChoicesScripts on them or anything or it will mess it up. Get the sys id from the sys_dictionary record of your fields-->
        <g:ui_element table="u_affected_users" field="u_table" id="ReplaceWithYourTableFieldSysId"></g:ui_element>
        <g:ui_element table="u_affected_users" field="u_user_conditions" id="ReplaceWithYourConditionFieldSysId"></g:ui_element>
      </TD>
    </TR>
    <TR>
      <TD>
        <button class="btn btn-primary" onclick="addUserQuery()">Filter</button>
      </TD>
    </TR>
    <TR>
      <TD> Please select the users you wish to add. </TD>
    </TR>
    <TR>
      <TD>
        <!-- Include the 'ui_slushbucket' UI macro -->
        <div>
          <g:ui_slushbucket name="sb" left_header="Left Side" right_header="Right Side">
          </g:ui_slushbucket>
        </div>
      </TD>
    </TR>
    <TR>
      <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" />
      </TD>
    </TR>
  </TABLE>
</j:jelly>

UI Page Client Script

function continueOK() {

    var values = sb.getValues(sb.getRightSelect());
    var taskID = g_form.getUniqueValue();

    //checks to make sure they did not select nothing
    if (values == '') {
        alert("At least one user must be selected");
        return;
    }
	//calls our script include that has the code we want to perform against the values in our list
    var ajax = new GlideAjax('UI_Page_Utils');
    ajax.addParam('sysparm_name', 'addUsers');
    ajax.addParam('sysparm_taskID', taskID);
    ajax.addParam('sysparm_values', values);
    ajax.getXML(addUserResponse);

}

function addUserResponse() {
    GlideDialogWindow.get().destroy();
    return true;
}


function continueCancel() {
    GlideDialogWindow.get().destroy();
    return false;
}

//This happens when the page loads
addLoadEvent(function() {

    //This clears the -- that starts out on the right
    sb.clearSelect(sb.getRightSelect());
    //This sets the table value 

	//The format for the id of the field is TableNameYouChoose.TableNameField then you set the value to whatever table you are wanting to have the filter apply to
    document.getElementById("u_affected_user.u_table").value = "sys_user";
    //This used to be a getElementById but when inspecting the code the id of this changes every time it is loaded
    var selectBoxChosen = document.getElementsByClassName("select2-chosen");
    //This sets the table field
    selectBoxChosen[0].innerHTML = "User [sys_user]";

    //This hides the table select box. The format is s2id_TableNameYouChoose.TableNameField
    document.getElementById("s2id_u_affected_user.u_table").hide();
    //This loads the filter field the format is (TableNameYouChoose.ConditionFieldName, TableNameField)
    loadFilterColumns('u_affected_user.u_user_conditions', 'u_table');
    //This may be uneeded I have it because otherwise you have to scroll to see the whole filter
    var filterRow = document.getElementsByClassName("col-xs-10 col-md-9 col-lg-8 form-field input_controls filter_controls-with-overflow");
	//This just sets the first one. If you were to have multiple filters on the page for different tables then you could iterate them 
    filterRow[0].style.width = "100%";



});


function addUserQuery() {
	
	//starts the loading dialog
	showLoadingDialog();

	//this gets the filter of the filter field The format is TableNameYouChoose.TableNameField should be the same as the first element in your loadEvent
    var userFilter = getFilter('u_affected_user.u_user_conditions');

	//This calls our script include where we pass in the query and it return us a list of users
    var userQueryAjax = new GlideAjax('UI_Page_Utils');

    userQueryAjax.addParam('sysparm_name', 'getUserList');
    userQueryAjax.addParam('sysparm_query', userFilter);

    userQueryAjax.getXML(userResults);
}

function userResults(response) {
    hideLoadingDialog();
	
	//Clears our list on the left
	sb.clearSelect(sb.getLeftSelect());
	//assigns our response to a var
    var userList = response.responseXML.documentElement.getAttribute("answer");
	//parses our JSON string to JSON so we can work with it
    userListJson = JSON.parse(userList);
	//Loops through our list and adds each of them to our slushbucet
    for (var i = 0; i < userListJson.length; i++) {
        var rowJson = userListJson[i];
		//adds them to our slushbucket with the format of (value,label)
        sb.addLeftChoice(rowJson['sys_id'], rowJson['name']);
    }

}

 

Script Include Code

var UI_Page_Utils = Class.create();
UI_Page_Utils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    //This function is to add the users selected to the table I want
    addUsers: function() {

        //Gets the parameters from the function
        var taskId = this.getParameter("sysparm_taskID");
        var values = this.getParameter("sysparm_values");

        //The slushbucket list comes in a comma seperated string. This turns that into an array
        var valueArrary = values.split(",");

        //Loops through the array and executes the code I want against each record
        for (var i = 0; i < valueArrary.length; i++) {
            var userID = valueArrary[i];

            var affectedUserGR = new GlideRecord("u_affected_user");
            affectedUserGR.u_affected_user = userID;
            affectedUserGR.u_outage = taskId;
            affectedUserGR.insert();
        }

        //You could return something of value here if you wanted.
        return true;


    },
    //This is the function to return a list of users based on a query you could add more parameters and be able to put in a table name and such
    getUserList: function() {

        var query = this.getParameter("sysparm_query");

        var userList = new GlideRecord("sys_user");
        //This is the query we pass in from our user
        userList.addEncodedQuery(query);
        userList.query();

        var userListArray = [];

        //This loops through our results and pushes them to an array. You can add any values you want here to the Array of objects. Just follow Json format because this is an array of objects
        while (userList.next()) {

            userListArray.push({
                "sys_id": userList.sys_id.toString(),
                "name": userList.name.toString()
            });
        }

        //this returns the list of users in JSON String format so you can parse it on the other end. If you dont to this it returns as a string that is the name of the object
        return JSON.stringify(userListArray);


    },

    type: 'UI_Page_Utils',
});

 

 

1 REPLY 1

Swarup Patra
Kilo Guru

Sure, here's a summarized version of your solution in bullet points:

1. You created a custom form with a Table and Condition field. This form is used to select the users that need to be added in bulk.

2. You created a UI Page. This page is used to display the list of users that are selected from the custom form.

3. You created a Script Include. This script is used to process the selected users and add them in bulk.

4. The Script Include uses the GlideRecord API to query the sys_user table and add the selected users.

5. The UI Page uses the GlideForm API to display the list of selected users and provide an interface for the user to confirm the bulk add operation.

6. The custom form uses the GlideDialogWindow API to display the UI Page when the user clicks on the 'Add Users' button.

7. The bulk add operation is performed when the user confirms the operation on the UI Page.

8. The Script Include uses the GlideUser API to add the selected users to the sys_user table.

9. The UI Page is refreshed after the bulk add operation is completed to display the updated list of users.

10. The custom form and the UI Page are linked using the 'name' attribute of the UI Page and the 'source' attribute of the GlideDialogWindow API.

Please note that this is a high-level summary of your solution and the actual implementation may vary based on the specific requirements and the ServiceNow instance configuration.


nowKB.com
If you want to know any information about Service Now . Visit to https://nowkb.com/home