How to populate list collector based on two fields?

shwethanair
Kilo Expert

Hello,

We have a requirement to populate the right side of List collector referencing to Application table with respect to two Select box field choices.

Selectbox - Category : Customer ,                               Selectbox - Category : Vendor

Selectbox - Type : Access Request ,                            Selectbox - Type : Deletion Request

List Collector - Application : A, B , C, D ,                       List Collector - Application : X, Y , Z

The Category and Type are mapped to Type and Category in CMDB application table , hence are pulling the choice values from there. Therefore whenever user chooses Type & Category in the Catalog for the respective mapped application should populate in the right side of list collector.

I have tried writing client script and Script include as follows but its not populating values somehow.

Please let me know where I need to make correction.

Script Include:

var getApplications = Class.create();
getApplications.prototype = Object.extendsObject(AbstractAjaxProcessor, {
selectAppl: function() {
var list = [];
var typ = this.getParameter('sysparm_type');
var ctg = this.getParameter('sysparm_category');
var parm = this.getParameter('sysparm_view');

var jsonArr = [];

var appl = new Gliderecord ('cmdb_ci_web_application');
appl.addQuery('u_type', typ);
appl.addQuery('u_category', ctg);
appl.query();
while(appl.next()){
if(parm == 'portal'){
list.push(appl.name);
}

else if(parm == 'native'){
var obj = {};
obj.name = appl.name;
obj.sys_id = appl.name.toString();
jsonArr.push(obj);
}

}

if(parm == 'portal')
return list.toString();
else
return JSON.stringify(jsonArr);

},

type: 'getApplications'
});

 

Onchange client script :

function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
g_form.clearValue('select_appli_list');
var ctg = g_form.getValue('category');
var parm = '';
if (window === null)
parm = 'portal';
else
parm = 'native';

var ajax = new GlideAjax('getApplications');
ajax.addParam('sysparm_name', 'selectAppl');
ajax.addParam('sysparm_type', newValue);
ajax.addParam('sysparm_category', ctg);
ajax.addParam('sysparm_view', parm);
ajax.getXML(populateValues);
}

function populateValues(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
var arr = answer.split('||');

// give here the list collector variable name
if (window === null) {
g_form.setValue('select_appli_list', arr[0]); // Mobile/Portal Compatible

} else {
addItemstoList('select_appli_list', answer); // Native Compatible
}
}
function addItemstoList(listCollector, applList) {

var parser = JSON.parse(applList);

var arrSysId = [];
var arrName = [];
for(var i=0;i<parser.length;i++){
arrName.push(parser[i].name);
arrSysId.push(parser[i].sys_id.toString());
}

var varName = listCollector;
var leftBucket = gel(varName + '_select_0');
var rightBucket = gel(varName + '_select_1');
var rightOptions = leftBucket.options;
var rightIDs = [];
//Remove --None--
for (var k= 0; k < rightOptions.length; k++) {
var value = rightOptions[k].innerHTML;
if (value == '--None--') {
leftBucket.remove(0);
}
}
// Add new options
if (arrName.length > 0) {
var myCIArray = arrName.toString().split(',');
for (var j = 0; j < myCIArray.length; j++) {
addOption(rightBucket, arrSysId[j], myCIArray[j]);
moveSelectedOptions(rightOptions, leftBucket , rightBucket);
sortSelect(rightBucket);
leftBucket.onchange();
}
}

// sort the buckets
sortSelect(rightBucket);
}

1 ACCEPTED SOLUTION

Brad Bowman
Kilo Patron
Kilo Patron

There are a couple of different ways to do this, but going down the path you were on, these scripts will work in Service Portal and the Native UI for any number of records in the table.  The same client script should be used onChange of Category and Type in case the requester populates them out of order.  You can also add a reference qualifier on the List Collector variable so that onLoad, invalid Applications cannot be selected

javascript:"u_category=" + current.variables.category + "^u_type=" + current.variables.type

Client Script, with Isolate script box unchecked

function onChange(control, oldValue, newValue, isLoading) {
 if (isLoading || newValue == '') {
  return;
 }

 g_form.clearValue('select_appli_list');
 var ctg = g_form.getValue('category');
 var typ = g_form.getValue('type');
 if(ctg && typ){
  var parm = '';
  if (window === null)
   parm = 'portal';
  else
   parm = 'native';

  var varName = 'select_appli_list';// name of the list collector variable
  var filterString = 'u_category=' + ctg + '^u_type=' + typ;
  //first reset the filter (left side) based on the 2 variables
  if(parm == 'portal'){
   var myListCollector = g_list.get(varName);
   myListCollector.reset();
   myListCollector.setQuery(filterString);
  }
  else{
   window[varName + 'g_filter'].reset();
   window[varName + 'g_filter'].setQuery(filterString);
   window[varName + 'acRequest'](null);
  }
  //now populate the Service Portal variable 
  if(parm == 'portal'){  
   var ajax = new GlideAjax('getApplications');
   ajax.addParam('sysparm_name', 'selectAppl');
   ajax.addParam('sysparm_type', typ);
   ajax.addParam('sysparm_category', ctg);
   ajax.getXML(populateValues);

   function populateValues(response) {
    var answer = response.responseXML.documentElement.getAttribute("answer");
    var arr = answer.split('||');
    //arr[1] has the sys_id of the applications 
    //arr[0] has the display name of the applications 
    g_form.setValue('select_appli_list', arr[1], arr[0]); 
   }
  }
  else{
   //or move all selections from the left side to right side
   //wrapped in a timeout to give the filter time to reset
   //adjust the number (3000) lower if the move is waiting too long after the new choices are loaded, or higher if the move is attempted before the filter is done loading - so the incorrect values are moved to the right side
   window.setTimeout(function(){
    var leftBucket = gel(varName + '_select_0');
    var rightBucket = gel(varName + '_select_1');
    var selectedOptions = leftBucket.options;
    var selectedIDs = new Array();
    var index = 0;
    for(var i = 0; i < selectedOptions.length; i++){
     selectedIDs[index] = i;
     index++;
    }
    rightBucket.options.length = '0';
    moveSelectedOptions(selectedIDs, leftBucket, rightBucket);
    sortSelect(rightBucket);
   }, 3000);
  }
 }
}  

Script Include, with Client callable box checked

var getApplications = Class.create();
getApplications.prototype = Object.extendsObject(AbstractAjaxProcessor, { 
 
selectAppl: function() {
 var name_arr = []; 
 var sys_id_arr = []; 
 var typ = this.getParameter('sysparm_type');
 var ctg = this.getParameter('sysparm_category');
 var appl = new GlideRecord ('cmdb_ci_web_application');
 appl.addQuery('u_type', typ);
 appl.addQuery('u_category', ctg);
 appl.query();
 while(appl.next()){
  name_arr.push(appl.name.toString()); 
  sys_id_arr.push(appl.sys_id.toString());
 }
 return name_arr.toString() + '||' + sys_id_arr.toString();
 
},
type: 'getApplications'
});

 

View solution in original post

7 REPLIES 7

Brad Bowman
Kilo Patron
Kilo Patron

There are a couple of different ways to do this, but going down the path you were on, these scripts will work in Service Portal and the Native UI for any number of records in the table.  The same client script should be used onChange of Category and Type in case the requester populates them out of order.  You can also add a reference qualifier on the List Collector variable so that onLoad, invalid Applications cannot be selected

javascript:"u_category=" + current.variables.category + "^u_type=" + current.variables.type

Client Script, with Isolate script box unchecked

function onChange(control, oldValue, newValue, isLoading) {
 if (isLoading || newValue == '') {
  return;
 }

 g_form.clearValue('select_appli_list');
 var ctg = g_form.getValue('category');
 var typ = g_form.getValue('type');
 if(ctg && typ){
  var parm = '';
  if (window === null)
   parm = 'portal';
  else
   parm = 'native';

  var varName = 'select_appli_list';// name of the list collector variable
  var filterString = 'u_category=' + ctg + '^u_type=' + typ;
  //first reset the filter (left side) based on the 2 variables
  if(parm == 'portal'){
   var myListCollector = g_list.get(varName);
   myListCollector.reset();
   myListCollector.setQuery(filterString);
  }
  else{
   window[varName + 'g_filter'].reset();
   window[varName + 'g_filter'].setQuery(filterString);
   window[varName + 'acRequest'](null);
  }
  //now populate the Service Portal variable 
  if(parm == 'portal'){  
   var ajax = new GlideAjax('getApplications');
   ajax.addParam('sysparm_name', 'selectAppl');
   ajax.addParam('sysparm_type', typ);
   ajax.addParam('sysparm_category', ctg);
   ajax.getXML(populateValues);

   function populateValues(response) {
    var answer = response.responseXML.documentElement.getAttribute("answer");
    var arr = answer.split('||');
    //arr[1] has the sys_id of the applications 
    //arr[0] has the display name of the applications 
    g_form.setValue('select_appli_list', arr[1], arr[0]); 
   }
  }
  else{
   //or move all selections from the left side to right side
   //wrapped in a timeout to give the filter time to reset
   //adjust the number (3000) lower if the move is waiting too long after the new choices are loaded, or higher if the move is attempted before the filter is done loading - so the incorrect values are moved to the right side
   window.setTimeout(function(){
    var leftBucket = gel(varName + '_select_0');
    var rightBucket = gel(varName + '_select_1');
    var selectedOptions = leftBucket.options;
    var selectedIDs = new Array();
    var index = 0;
    for(var i = 0; i < selectedOptions.length; i++){
     selectedIDs[index] = i;
     index++;
    }
    rightBucket.options.length = '0';
    moveSelectedOptions(selectedIDs, leftBucket, rightBucket);
    sortSelect(rightBucket);
   }, 3000);
  }
 }
}  

Script Include, with Client callable box checked

var getApplications = Class.create();
getApplications.prototype = Object.extendsObject(AbstractAjaxProcessor, { 
 
selectAppl: function() {
 var name_arr = []; 
 var sys_id_arr = []; 
 var typ = this.getParameter('sysparm_type');
 var ctg = this.getParameter('sysparm_category');
 var appl = new GlideRecord ('cmdb_ci_web_application');
 appl.addQuery('u_type', typ);
 appl.addQuery('u_category', ctg);
 appl.query();
 while(appl.next()){
  name_arr.push(appl.name.toString()); 
  sys_id_arr.push(appl.sys_id.toString());
 }
 return name_arr.toString() + '||' + sys_id_arr.toString();
 
},
type: 'getApplications'
});

 

Hello Brad,

I am finding issue in the portal part. The applications are not autopopulating , 1 application populates but clicking on the field can see the duplicate for that and other application, need to click on them and populate. Moreover on submission duplicate tasks are getting created.

find_real_file.png

Sorry, change this line in the script include - I'll correct it above also

sys_id_arr.push(appl.sys_id.toString());

Duplicate tasks sounds unrelated to populating a list collector based on 2 variable choices