THURSDAY, FEBRUARY 09, 2012

Changing the Filter of a List Collector Variable via Client Script

I

f you’ve worked with the Service-now.com service catalog much, you’ve probably realized that there are some differences between the service catalog interface and the traditional forms that are used throughout the rest of the tool. The intention of this is to make the experience a little bit better for end users of the system but it also means that you, as an administrator, have to learn a few new tricks to deal with those differences.

One of these differences is the List collector variable. It allows the user to select multiple items from a list of items and optionally filter those items to help in their selection. One of the most common requests I see about this type of variable deals with how to handle the filter at the top of the list collector. Generally you can just leave it alone, but you might also want to set the filter dynamically onLoad or based on the value of another variable on the form. Depending on the situation and the number of items in the list collector table you may want to remove the filter portion completely.

List Collector Filter


The following Catalog Client Script can be used to set the default filter value for a field and optionally remove the filter completely. It assumes that your List collector variable is named ‘configuration_items’. By default it sets a filter where ‘name != null’ and ‘sys_class_name (CI type)’ is anything. Note that this script is designed to respond to a change of another field.

As of the Winter 2010 Stable 2 release, it is now possible to hide the filter portion of a list collector variable completely. This can be accomplished by adding the ‘no_filter’ attribute to the ‘Attributes’ field on the variable form. The client script method may still be useful if you want to show/hide the filter conditionally however.
function onChange(control, oldValue, newValue, isLoading) {
   //Find the filter elements
   var fil = gel('ep');
   //Hide the filter elements by un-commenting the following lines
   /*fil.rows[0].style.display = 'none';
   fil.rows[1].style.display = 'none';
   fil.nextSibling.rows[0].style.display = 'none'; //Filter description text*/


   //Reset the filter query
   configuration_itemsg_filter.reset();  
   var answer = 'name!=NULL^sys_class_nameANYTHING';  
   configuration_itemsg_filter.setQuery(answer);
   configuration_itemsacRequest(null);
}
Note: If you are trying to filter your list collector in an onLoad script, you’ll probably have to modify the script so that it waits for the list collector to be rendered before it sets the filter. Below is a modification of the same script with the addition of a 1 second wait before applying the filter.
function onLoad() {
   //Apply a default filter to the list of CIs
   //Hide the list collector until we've set the filter
   g_form.setDisplay('configuration_items', false);
   //Wait for the list collector to be rendered
   setTimeout(setMyFilter,1000);
}

function setMyFilter() {
   //Find the filter elements
   var fil = gel('ep');
   //Hide the filter elements by un-commenting the following lines
   /*fil.rows[0].style.display = 'none';
   fil.rows[1].style.display = 'none';
   fil.nextSibling.rows[0].style.display = 'none'; //Filter description text*/


   //Reset the filter query
   configuration_itemsg_filter.reset();
   var answer = 'name!=NULL^sys_class_nameANYTHING';
   configuration_itemsg_filter.setQuery(answer);
   configuration_itemsacRequest(null);
   //Redisplay the list collector variable
   g_form.setDisplay('configuration_items', true);
}

Comments

Posted On
Jan 21, 2010
Posted By
alli

Hi,

configuration_itemsg_filter.setQuery(answer);

there is no space needed here ? between configuration_items and g_filter.setQuery(answer);

I can’t seem to make it work

Posted On
Jan 21, 2010
Posted By
Mark Stanger

No space is necessary. Just make sure that the name of your variable is ‘configuration_items’ or that you change the script to match your variable name.

Posted On
Feb 01, 2010
Posted By
alli

Hi Mark,

I still can’t make this work,

I copies your text, even named my variable “configuration_items”

still won’t work.

any other instructions I need?

Posted On
Feb 01, 2010
Posted By
Mark Stanger

This should work for any instance on newer code. You might try implementing the same thing at https://demo.service-now.com and see if you can get it to work there first. If you are working on an older build, then you might try omitting ‘configuration_items’ everywhere in the script and see if that works for you. Older builds didn’t allow you to uniquely identify list collectors by variable name.

Posted On
Feb 01, 2010
Posted By
alli

Hi Mark,

just tested it on demo, (dev laptop item)

name of filter is “filter”

still not working

Alli

Posted On
Jan 28, 2010
Posted By
Ruth Porter

Hi there,

I have tried this but get an error saying var_nameg_filter undefined.

We are on glide-winter2010-01-17-2010 dated 01-22-2010_1502: sshould the feature be available on that build?

Thanks in advance, Ruth

Posted On
Jan 28, 2010
Posted By
Mark Stanger

It is. I’m using it on that build in my personal instance. Did you copy the script exactly as it appears above? Did you change it so that it has the name of your variable? Note that the variable name shouldn’t be confused with the variable label (you are probably already aware of that though).

Posted On
Feb 02, 2010
Posted By
Mark Stanger

Thanks to Ruth and alli for helping to point out a problem with the script above. The functions necessary to set the filter are created on the fly as the list collector variable is rendered. Because of this, if you run the script ‘onLoad’, the functions might not be available at the time the script runs. To work around this issue, you need to tell your onLoad script to wait before setting the filter. I’ve provided a second example above that shows you how to do that.

Posted On
Feb 03, 2010
Posted By
Andrew Wilmut

Thank you! That script is perfect!

Posted On
Apr 05, 2010
Posted By
John Roschella

Mark

Thanks for the help. The delay was the trick I needed to get the filter to load correctly.

Posted On
Apr 19, 2010
Posted By
Bill Collins

Awesome Mark…Thanks!

Posted On
Apr 19, 2010
Posted By
Bill Collins

Awesome Mark…Thanks!

All works for me, but the filter does not run. My list is on sys_user_group. I am filtering on group type. The filter is set but returns no groups. Selecting Run Filter does not work. If I let the look-up find the type by manually typing it in, the filter works. Ideas? Do group types have values different than the labels?

Bill

P.S. Thank you very much for the SNCguru

Posted On
Apr 19, 2010
Posted By
Mark Stanger

Hey Bill, I’m glad you’ve found something useful here. You’re on the right track. Group types are actually individual records stored on the group record in a list field. Group types are stored in the ‘sys_user_group_type’ table. Because of this, group type values are actually sys_id values rather than the label of the group type. I think that’s probably your problem.

Posted On
Apr 23, 2010
Posted By
Bill Collins

The sys_id worked like a dream. I didn’t try getDisplayValue. Thank you.

Posted On
Mar 21, 2011
Posted By
Jim Coyne

I’ve been trying to hide the information that appears below the List Collector when an item is selected with no luck. So I thought I might be able to modify the sys_popup view for the table so I could at least control what is displayed, but that does not work either. Any ideas?

Posted On
Mar 21, 2011
Posted By
Mark Stanger

You should be able to hide the information below the list collector in a client script like this…

gel('YOURVARNAMEHERErecordpreview').hide();

If that doesn’t work, then you can customize the fields below a slushbucket for that table like this…
http://www.servicenowguru.com/system-ui/customizi…

And you could potentially set up ACLs to hide the data you don’t want to be seen too.

Posted On
Mar 21, 2011
Posted By
Jim Coyne

Aha, gel(‘YOURVARNAMEHERErecordpreview’).hide(); worked!!! Thanks Mark

Posted On
Jun 01, 2011
Posted By
Ashish

Hi Mark,

I tried using the code above, referencing the cmdb_ci table. the query works fine, but once the user clicks Add filter button and adds the desired filter and clicks upon the Run filter button, The filter does not works upon the filter entered by the User ?

What can i do??

P.S : thanks a lot to Service-now Guru. Its Awesome.

Posted On
Jun 01, 2011
Posted By
Mark Stanger

It should work. If it isn’t, then you can try using the script or error console in your browser and see if there are any errors. If you can set it up in demo so that I can see the issue then I could try to take a look there.

Posted On
Jul 25, 2011
Posted By
Ashish

Hi Mark, Sorry for the late reply. I have gone through it and was able to make it work. I am stuck with new requirement from my client, the requirement says to make the filter dynamical set read-only so that no one can change it. Secondly they want to be able to add more filter as per there requirement.
Can u please tell-me how can I make dynamic filters readonly??

thanx a lot for replying, :)

Posted On
Jul 25, 2011
Posted By
Mark Stanger

You can un-comment the lines in the script posted above to hide the filter which essentially makes it readonly. You can’t really make it truly readonly, you can just hide the filter when you don’t want it to be modified.

Posted On
Jul 27, 2011
Posted By
sandy

hi,
this solution does not work on firefox. is there a work around for this?
thank you,
sandy

Posted On
Jul 27, 2011
Posted By
Mark Stanger

Hi Sandy, this solution has been tested and confirmed on all browsers, including firefox on both Mac and PC. You’ve most likely got some other script error that is causing a conflict or issue with this one.

Posted On
Jul 28, 2011
Posted By
sandy

this is the code i am using.. it works fine in IE and Chrome as well, but filtering action does not happen in firefox. Please let me know if I am missing anything in this code.

function onLoad() {        
    var control = g_form.getControl('search_string');
    var fil = gel('ep');   
    control.onkeyup = myKeyUp;
    g_form.setDisplay('StartHiddenItems', false);
   
    // set filter display
    fil.rows[0].style.display = 'none';
    fil.rows[1].disabled=true;
    fil.rows[1].style.display = 'none';
}

function myKeyUp() {
    key = event.keyCode || event.which;
    if (key == 13) {
        //alert("You pressed return");
        var searchText = g_form.getValue('search_string');
        var listFilter = '';
                if(g_form.getValue('CurrentAssignedTo').toString().length > 0){
                listFilter += 'assigned_to='+g_form.getValue('CurrentAssignedTo');
               
                }
                else {
                listFilter += 'assigned_to=NULL';
                }
                listFilter += '^hardware_status!=retired' ;
        listFilter += '^nameLIKE'+searchText;
        listFilter += '^ORserial_numberSTARTSWITH'+searchText;
        listFilter += '^ORassigned_to.employee_number='+searchText;
        listFilter += '^ORassigned_to.nameSTARTSWITH'+searchText;      
        listFilter += '^ORu_rfid='+searchText;
        //listFilter += '^ORlocation.name='+searchText;
        //listFilter += '^ORsupport_group.name='+searchText;
       
        EquipmentNamesg_filter.reset();
        EquipmentNamesg_filter.setQuery(listFilter);
        EquipmentNamesacRequest(null);
    }
}
Posted On
Jul 28, 2011
Posted By
Mark Stanger

You’ve customized this to use an onKeyUp event. I’m guessing that’s where the problem lies. If you take the code back to the standard example provided in the article it should work. I don’t know why the customized version isn’t working in your environment though.

Posted On
Jul 29, 2011
Posted By
Scott Hall

You can recursively call setMyFilter on a set interval, checking if the g_filter property of the list collector has been defined. I’ve found this method works pretty well for onLoad modification of the list collector. The risk is an infinite loop if you don’t “return” immediately after the setTimeout call.

function onLoad() {
   setMyFilter();
}

function setMyFilter() {
   //Test if the g_filter property is defined on our list collector.
   //If it hasn't rendered yet, wait 100ms and try again.
   if (typeof(configuration_itemsg_filter) == 'undefined' ) { setTimeout(setMyFilter,100); return; }

   //What lies below will only get executed if the list collector has rendered and has g_filter properties available.
   var fil = gel('ep');

   //Reset the filter query
   configuration_itemsg_filter.reset();
   var answer = 'name!=NULL^sys_class_nameANYTHING';
   configuration_itemsg_filter.setQuery(answer);
   configuration_itemsacRequest(null);
}
Posted On
Aug 01, 2011
Posted By
Mark Stanger

Cool. Thanks for sharing your solution!

Posted On
Jul 29, 2011
Posted By
sandy

event was not geting recognized inside firefox. i have modified myKeyUp() to myKeyUp(e) and it worked.
Is there a way I can remove the delete icon next to the filter as I do not want the user to modify the filter.
thank you,
sandy

Posted On
Sep 14, 2011
Posted By
Steve Darity

Great Article. Works like a Charm! Thanks.

Posted On
Nov 29, 2011
Posted By
Brian Broadhurst

Hi Mark,

great tip, and proving very useful! I have a question that maybe you can answer. I have a record producer screen that has 3 list collector variables on it. I want to hide the filter on one of the variables, but not the other two. The gel(‘ep’) command doesn’t distinguish between the variables, so how can I target the specific variable that I want?

Brian

Posted On
Nov 29, 2011
Posted By
Mark Stanger

Good question. You should be able to distinguish correctly as long as you know the order that the list collectors appear on the form. Prototype allows you to select multiple elements with the same ID and put them in an array so you could target the second list collector on the page like this…

$$('#ep')[1];
Posted On
Jan 18, 2012
Posted By
Eric Roth

I am new to SN and have probably a basic question. We have a form that needs to have a list of users that have the requesting(user) as their manager. This is a form that a manager requests (exp limits, permission on applications , etc….) what is the java script or best way to accomplish this

thanks

Posted On
Jan 19, 2012
Posted By
Mark Stanger

If you’re using the solution described in this article you would need to set up a list collector variable to display those users. You could apply a filter to the list collector by modifying the ‘answer’ line to be something like this…

var answer = 'manager=' + g_user.userID;
Posted On
Jan 19, 2012
Posted By
ND

Hi,

I am trying to use list_collector variable ( Service Catalog). I have created a table and it has only one column. This table doesn’t inherit any table. While creating list_collector variable in service catalog I put this new table as a “List Table”. I am expecting to get all value from the table in available section. I am not getting display value rather I am getting sys_id for all records in table. ( Table only have one column and many record created for that column).

Could you please help me to get the actual display value. Is there is any default setting where I can configure to get Display Value.

Posted On
Jan 19, 2012
Posted By
Mark Stanger

You need to personalize the dictionary for some field in that table and check the ‘Display’ checkbox.

Posted On
Jan 19, 2012
Posted By
ND

Thanks for lighting fast reply. It worked.

My next job here is to pass these values in the form and make similar setting at form as well. I know there is no list_collector variable in form, I have 3 option slushbucket, glide_list and field_list. I worked a bit on glide_list on form ( not getting value from catalog). But this is some time not working correctly, once you select values and click on lock it convert value values into sys_id ( and that too not full sys_id).

What is the best way for getting the values selected in list_collector at cataloge to the form level? Also what variable I shoulw use at the form leve? Is there is any document available for this?

Posted On
Jan 20, 2012
Posted By
Mark Stanger

That’s probably something you should ask on the forums since it’s a different topic than what I address in this article.

Leave a Reply


Notify me of followup comments via e-mail. You can also subscribe without commenting.

Latest Comments

  • Aric: Finally figured out what I was doing wrong, incase someone else wants to do this. Mark is correct about needing...
  • Mark Stanger: You’ll probably need at least 3 total ACLs then. You’ll need one...
  • Mark Stanger: Hey Paul, I assume you’re talking about ‘task_ci’, not ‘task_group. If so, the...
  • ND: Hi Mark, This is cool. How can I do same at the form level. I have created a slushbucket variable and I want to...