Changing the Filter of a List Collector Variable via Client Script

///Changing the Filter of a List Collector Variable via Client Script

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 - Filtered

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.

Please note that it is 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. This also works for Service Portal! Just make sure you set the ‘UI type’ field on the client script form to ‘Both’.

function onChange(control, oldValue, newValue, isLoading) {
    //Apply a filter to the list collector variable
    var collectorName = 'configuration_items';
    var filterString = 'name!=NULL^sys_class_nameANYTHING';
   
    //Try Service Portal method
    try{
        var myListCollector = g_list.get(collectorName);
        myListCollector.reset();
        myListCollector.setQuery(filterString);
    }
    //Revert to Service Catalog method
    catch(e){
        //Find and hide the filter header elements (optional)
        //Simple method for items with only one list collector
        //$('ep').select('.row')[0].hide();
        //Advanced method for items with more than one list collector (more prone to upgrade failure)
        //var el = $('container_' + g_form.getControl(collectorName).id).select('div.row')[0].hide();
       
        //Reset the filter query
        window[collectorName + 'g_filter'].reset();
        window[collectorName + 'g_filter'].setQuery(filterString);
        window[collectorName + 'acRequest'](null);
    }
}
Note: If you are trying to filter your list collector in an onLoad script, you have to modify the script so that it waits for the list collector to be rendered before it sets the filter. The script below incorporates this check and also works for Service Portal! Just make sure you set the ‘UI type’ field on the client script form to ‘Both’.

function onLoad() {
    //Apply a default filter to the list collector variable
    var collectorName = 'configuration_items';
    var filterString = 'name!=NULL^sys_class_nameANYTHING';
   
    //Try Service Portal method
    try{
        var myListCollector = g_list.get(collectorName);
        myListCollector.reset();
        myListCollector.setQuery(filterString);
    }
    //Revert to Service Catalog method
    catch(e){
        //Hide the list collector until we've set the filter
        g_form.setDisplay(collectorName, false);
        setCollectorFilter();
    }
   
    function setCollectorFilter(){
        //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(window[collectorName + 'g_filter']) == 'undefined'){
            setTimeout(setCollectorFilter, 100);
            return;
        }
        //Find and hide the filter elements (optional)
        //Simple method for items with only one list collector
        //$('ep').select('.row')[0].hide();
        //Advanced method for items with more than one list collector (more prone to upgrade failure)
        //var el = $('container_' + g_form.getControl(collectorName).id).select('div.row')[0].hide();
       
        //Reset the filter query
        window[collectorName + 'g_filter'].reset();
        window[collectorName + 'g_filter'].setQuery(filterString);
        window[collectorName + 'acRequest'](null);
        //Redisplay the list collector variable
        g_form.setDisplay(collectorName, true);
    }
}
By | 2018-07-09T15:01:30+00:00 January 13th, 2010|Categories: Client scripts|Tags: , , |119 Comments

About the Author:

Mark has worked in the IT industry since 2002 and with ServiceNow since 2007. He is the founder and creator of SN | Guru and the co-founder of Crossfuze, one of the worlds leading ServiceNow consulting partners. Prior to co-founding Crossfuze, he worked for ServiceNow as a Senior Architect on the Professional Services team. He has personally led dozens of successful implementations encompassing every part of the ServiceNow platform. He is also responsible for designing and developing groundbreaking ServiceNow solutions and best practices in the form of various applications, turnkey solutions, and integrations during his tenure at ServiceNow, Crossfuze and, of course, SN | Guru. These solutions are used today by ServiceNow administrators and consultants alike in hundreds of ServiceNow instances around the world!

119 Comments

  1. alli January 21, 2010 at 12:37 am - Reply

    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

    • Mark Stanger January 21, 2010 at 12:39 am - Reply

      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.

      • alli February 1, 2010 at 3:53 am - Reply

        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?

        • Mark Stanger February 1, 2010 at 4:34 am - Reply

          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.

          • alli February 1, 2010 at 11:22 pm - Reply

            Hi Mark,

            just tested it on demo, (dev laptop item)

            name of filter is “filter”

            still not working

            Alli

  2. Ruth Porter January 28, 2010 at 12:56 am - Reply

    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

    • Mark Stanger January 28, 2010 at 1:03 am - Reply

      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).

  3. Mark Stanger February 2, 2010 at 1:15 am - Reply

    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.

  4. Andrew Wilmut February 3, 2010 at 5:59 am - Reply

    Thank you! That script is perfect!

  5. John Roschella April 5, 2010 at 7:16 am - Reply

    Mark

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

  6. Bill Collins April 19, 2010 at 6:25 am - Reply

    Awesome Mark…Thanks!

  7. Bill Collins April 19, 2010 at 6:35 am - Reply

    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

    • Mark Stanger April 19, 2010 at 6:39 am - Reply

      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.

      • Bill Collins April 23, 2010 at 7:24 am - Reply

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

  8. Jim Coyne March 21, 2011 at 3:03 am - Reply

    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?

    • Mark Stanger March 21, 2011 at 4:30 am - Reply

      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…
      https://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.

  9. Jim Coyne March 21, 2011 at 1:56 pm - Reply

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

    • David April 15, 2014 at 8:31 pm - Reply

      Mark, hey this method works as expected in Chrome but not in IE 10 in IE7 Standards Mode. Suggestions? Gracias in advance….

  10. Ashish June 1, 2011 at 7:31 am - Reply

    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.

    • Mark Stanger June 1, 2011 at 7:44 am - Reply

      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.

      • Ashish July 25, 2011 at 8:06 am - Reply

        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, 🙂

        • Mark Stanger July 25, 2011 at 4:39 pm - Reply

          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.

  11. sandy July 27, 2011 at 4:12 pm - Reply

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

    • Mark Stanger July 27, 2011 at 4:54 pm - Reply

      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.

  12. sandy July 28, 2011 at 11:13 am - Reply

    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);
        }
    }
    • Mark Stanger July 28, 2011 at 11:37 am - Reply

      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.

  13. Scott Hall July 29, 2011 at 4:35 pm - Reply

    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);
    }
    • Mark Stanger August 1, 2011 at 9:08 am - Reply

      Cool. Thanks for sharing your solution!

    • John Caruso March 27, 2012 at 2:48 pm - Reply

      I’m not positive but I believe this works as well (seems to be working for me) and leverages Prototypes function for waiting for the DOM to be loaded:

      function onLoad() {
          document.observe('dom:loaded', setMyFilter);
      }

      function setMyFilter() {
          ...
      }

      Or the anonymous approach:

      function onLoad() {
          document.observe('dom:loaded', function() {
              // set filter here
          });
      }
      • Mark Stanger March 27, 2012 at 4:15 pm - Reply

        Thanks John! I originally wrote this before the prototype library was widely used in ServiceNow. This is a great idea. I prefer ‘Event.observe’ to wait for the load event to do what you describe. I’ve updated the code above to include this check.

        • John Caruso March 27, 2012 at 5:03 pm - Reply

          Mark,

          The functional equivalent using ‘Event.observe’ syntax for what I coded would be:

          Event.observe(document, ‘dom:loaded’, function() {
              ...
          });

          Is there are reason why you choose the window.onload event instead? Per: http://www.prototypejs.org/api/document/observe :

          “If you used window.onload before you might want to switch to dom:loaded because it will fire immediately after the HTML document is fully loaded, but before images on the page are fully loaded. The load event on window only fires after all page images are loaded, making it unsuitable for some initialization purposes like hiding page elements (so they can be shown later).”

          I chose the ‘dom:loaded’ event because it appears to be the equivalent to using

          $(document).ready(function(){...});

          in jQuery.

          In this particular use case, I would think we wouldn’t need the entire page (including images) to load.

          John

          • Mark Stanger March 27, 2012 at 5:20 pm - Reply

            No particular reason. Just the convention I’m used to.

  14. sandy July 29, 2011 at 5:14 pm - Reply

    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

  15. Steve Darity September 14, 2011 at 10:17 am - Reply

    Great Article. Works like a Charm! Thanks.

  16. Brian Broadhurst November 29, 2011 at 1:27 am - Reply

    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

    • Mark Stanger November 29, 2011 at 5:38 am - Reply

      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];
    • Jason Thomas March 7, 2012 at 5:33 am - Reply

      Hi Brian

      You may like to know that you can add ‘no_filter’ in the attribute field on the list collector to hide the filters now.

      Not sure how recent this is.

      http://wiki.service-now.com/index.php?title=Variable_Types#List_Collector

  17. Eric Roth January 18, 2012 at 6:19 pm - Reply

    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

    • Mark Stanger January 19, 2012 at 7:13 am - Reply

      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;
      • ND January 19, 2012 at 9:48 pm - Reply

        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.

        • Mark Stanger January 19, 2012 at 9:51 pm - Reply

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

          • ND January 19, 2012 at 10:11 pm - Reply

            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?

            • Mark Stanger January 20, 2012 at 5:38 am

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

          • Amit November 24, 2012 at 1:04 pm - Reply

            Checking the display box works ..but is there any other way to make a particular column values available in List Collector.

            Can you please help me as I cannot make dictionary changes.

  18. Matt March 5, 2012 at 3:16 pm - Reply

    Hey Mark,
    Is there a way to apply the filter to the right box in list collector?

    • Mark Stanger March 6, 2012 at 4:19 am - Reply

      There’s not a way that I’m aware of to do that.

  19. damodar reddy March 7, 2012 at 10:58 pm - Reply

    Hi Mark,
    I have a query on setting filters…
    In catalog item Server-StorageBox
    I create a request for Server-StorageBox and once the request is fullfilled it will create a relationship in a table.
    Now i want to reset a filter in this way..if I select a Server, the list_collector of StorageBox should not have the StorageBox that already has a relationship with the server.

    • Mark Stanger March 8, 2012 at 6:05 am - Reply

      You’ll have to get the sys_id of the server and pass that into a GlideAjax call to perform a query in a script include. Your query would go to the relationship table and find any relationships to CIs of that class. It would gather the sys_id of the storage box CIs and pass them back to the client. You could then set a ‘sys_idIN’ filter on your list collector.

  20. Peter June 12, 2012 at 5:08 pm - Reply

    HI,
    On the define relationships form for CIs, I am interested in being able to make changes to the choice list in the filter when the class field is choosen. Is this the area wher it can be done.
    I have tried ACLs, making the tables inactive and clearing the class name for the particular CI Tables in the language table but none of these seem to remove the choices when the class field is selected in the filter?
    Am I missing something else that would provide that outcome ?

    • Mark Stanger June 12, 2012 at 7:54 pm - Reply

      Hi Peter,
      Unfortunately I think you’re stuck with what you see in that filter. That whole page isn’t really customizable at all.

  21. Jerry July 11, 2012 at 7:35 am - Reply

    Hi Marc,

    do you now the what the meaning of the parameter of the XXX_acRequest(null) function is?
    The function itself is working asynchronously??

    Regards
    Jerry

    • Mark Stanger July 11, 2012 at 7:38 am - Reply

      I believe it’s synchronous but I’m not positive. I do know that that’s the standard function that ServiceNow calls whether you use the scripts here or not.

  22. Travis Henning August 27, 2012 at 7:30 pm - Reply

    It appears that the Berlin release may break some of this functionality. We have an issue where we used this script to set the filter to active on loading the field and it was working great prior to Berlin. We have a ticket opened with ServiceNow to see what changed. They’re saying the
    Event.observe(window, ‘load’, function()
    is not called correctly.
    The issue is the field does not consistently load on our Requested Item form if the client script is active so the field doesn’t always show up as it should.

    • Mark Stanger August 27, 2012 at 7:44 pm - Reply

      I’ve seen a couple of other issues in Berlin related to ‘Event.observe’ I hope ServiceNow support gives you a solution because ‘Event.observe’ is standard Prototype behavior…that ServiceNow ships with! You might have to use ‘setTimeout’ to create a small delay before the script actually executes.

      • Travis Henning August 31, 2012 at 7:34 am - Reply

        Unfortunately not good news from SN. They said it wasn’t a supported method in a client script. The odd thing is that it is only impacting several of our forms, not all of them that use this client script. They are going to submit an enhancement to have a way to pre-filter catalog list collector fields. So we should have an officially supported method sometime in 2014, if we’re lucky… 😉

        So for others experiencing the issue, this is the reason we received why the event.observer action doesn’t work:
        1. The onLoad function is called when the page has been loaded. The load order was changed in Berlin which is why the Event.observe(window, ‘load’…) worked in previous versions and does not work anymore. The use of the Event.observe to watch for window.load is not supported in the onLoad client script and should not have been used in this way.

        2. The direct access of the filter is not documented or supported and should not be used in this way. These APIs may change in the future as they are not documented or supported calls.

        • Mark Stanger August 31, 2012 at 9:44 am - Reply

          @Travis, thanks for the feedback. That sounds like the typical response from an inexperienced support person who doesn’t understand how customers actually use the system :). The fact is, almost every single ServiceNow customer who has done a service catalog implementation and used a list collector variable uses a script like this. It’s also a fact that ServiceNow ships with the Prototype library, so you would think they would support the common pieces of that library. Oh well :). This script is still very much a necessity though. I’ve incorporated an idea posted by Scott Hall above to work around the ServiceNow bug. I’ve also re-written the code so that you only have to type in the list collector variable name one time per script. The article above has been updated to reflect these changes. Give it a try and let me know how it goes!

  23. Phil September 4, 2012 at 11:09 pm - Reply

    I’m not sure I followed the comment trail here correctly so, I’ll jus ask. Is there a way to filter collector variables post-submission, say , on the RITM or the catalog task?

  24. Steve Arnold February 13, 2013 at 3:34 pm - Reply

    Mark, you are once again awesome…I had to modify your script slightly to allow me to set the filter on multiple list collectors in the same variable set (4 of them in this instance), and I came up with this Catalog Client Script:

    function onLoad() {
      setCollectorFilter('systemaccess','u_active=true');
      setCollectorFilter('accessreq','u_active=true');
      setCollectorFilter('busprofadd','u_active=true');
      setCollectorFilter('busprofrem','u_active=true');
    }

    function setCollectorFilter(collectorName, filterString) {
      g_form.setDisplay(collectorName, false);

      if (eval('typeof(' + collectorName + 'g_filter)') == 'undefined' ) {
         setTimeout(function() { setCollectorFilter(collectorName,filterString); }, 100);
         return;
      }

      eval(collectorName + 'g_filter.reset()');
      eval(collectorName + 'g_filter.setQuery("' + filterString + '")');
      eval(collectorName + 'acRequest(null)');

      g_form.setDisplay(collectorName, true);
    }
  25. Neha Gaikwad April 16, 2013 at 3:33 am - Reply

    This is great help, this is working perfectly for me thanks a for sharing such codes 🙂

  26. Erik Myrold October 28, 2013 at 4:00 pm - Reply

    Mi Mark,

    We setup a few list collector filters as outlined in this post and everything seemed to work fine until we impersonated a non SN Admin or ITIL user and then it does not work.

    We are on Berlin and we have a requirement to make the variables “read only” and we addressed that almost a year ago on all our catalog items by marking each of the variables “write = admin” (also found that tidbit on your site… 🙂 ). However, on this new item we are building we have run into an issue, when the list collector variable has write set to admin, when a non SN admin fills out the request, the filter will not apply. Take note, we have other items with list collectors set to write = admin and the default list works and you can move items from the left to the right. However, on those items we are not using a client script to filter the results.

    Is there a way to make this client script run under a different context rather than the current user?

    • Mark Stanger October 28, 2013 at 4:34 pm - Reply

      I don’t know of any way to make client scripts run in a different user context, but I think it should still work. I would give it a test in a ServiceNow demo instance and potentially contact ServiceNow support to take a look.

      • Erik Myrold October 28, 2013 at 4:50 pm - Reply

        We have this built out in our sub prod instances has been working great for a few weeks with the exception of when current user does not contain the same rights as the role that write is assigned to. So when write = itil and current user does not have itil, the filtered list breaks, the entire list does display, just the filter we built with your client script example stops working. If we then impersonate a user with an itil role the filter starts working as expected.

        In Demo they are running Calgary and we are on Berlin. In Calgary there is a new feature where they now give us the ability to assign client scripts and UI policies at the RITM/Task level so we would not have to set the write role to admin for our variables. Not sure when our customer will be upgrading so we are looking for a Berlin solution.

        Thanks so much for the quick reply!!! all the best, -e

  27. Dennis November 27, 2013 at 9:21 am - Reply

    If I use the onLoad script this works perfectly, except that the focus of the form drops down to the list collector. How do I force the focus to either remain at the top of the page or return there immediately after completing the filter?

    • Mark Stanger November 27, 2013 at 12:10 pm - Reply

      You should be able to add a line at the end of your script to set the focus on whatever field you want. Standard javascript has a ‘focus()’ method you can use. Something like this should work.

      $(g_form.getControl('YOURVARIABLENAMEHERE').id).focus();
  28. Tami June 2, 2014 at 12:52 pm - Reply

    Is there a way to sort the filtered list? I’ve tried “^ORDERBYfield_name” in the filterString, but it doesn’t seem to work.

    • Mark Stanger June 2, 2014 at 12:54 pm - Reply

      There isn’t currently a way to sort the results of a list collector.

      • Anupama January 19, 2015 at 11:15 pm - Reply

        Mark,
        Can i use the same script to filter “Look Up Select Box” type variable too?
        What changes do i need to make in your script?

        • Mark Stanger January 21, 2015 at 9:40 am - Reply

          No, you can’t. You would need to use client scripts to add and remove choices. Check out the ‘g_form’ api (addOption and removeOption) on the ServiceNow wiki for details.

  29. Billy Matthews February 19, 2015 at 11:23 am - Reply

    So you can also do this with just:

    “`
    addLateLoadEvent(function () {
    watch_listg_filter.setQueryAsync(‘active=true’);
    watch_listacRequest();
    });
    “`
    Inside of an OnLoad Script. Where “watch_list” is whatever you named your list collector.

    • Marek Filip June 7, 2016 at 2:55 am - Reply

      This actually worked for me! With list collector attribute ‘no_filter’ I’ve got pre-filtered list that can not be changed by user (no_filter attribute only hides filter on client).

    • Billy Matthews November 18, 2016 at 2:13 pm - Reply

      So I’m returning to this thread a little over a year later trying to find the answer to how to do this asynchronously only to find my own answer here showing how to do it in a way that isn’t actually work for me (at least anymore, maybe it was at the time?).

      After a bit more research I’ve found a way that does seem to work. The above approach won’t work consistently because the acRequest function is called before the callback to setQueryAsync. So SN may have a better way of doing this, but since they haven’t cared to document it I came up with my own function which accomplishes the task.

      function setListCollectorFilterAsync(listCollector, query) {
      var filter = window[listCollector + ‘g_filter’];
      var acRequest = window[listCollector + ‘acRequest’];

      filter.glideQuery = new GlideEncodedQuery(filter.tableName, query, function () {
      if (filter.destroyed)
      return;

      filter.reset();
      filter.build();

      if (filter.getFilterReadOnly())
      filter.setReadOnly(true);

      acRequest(null);
      });

      filter.glideQuery.parse();
      filter.queryProcessed = true;
      }

  30. LIZ August 21, 2015 at 8:03 am - Reply

    Hi Mark,

    Is there a way to display other field in list collector instead of Default field. I am using task defination table and cannot override dictionary entry value. I wanted to display other field instead of “Name”. Please advice.

    • Mark Stanger August 21, 2015 at 8:06 am - Reply

      There isn’t. You can only see the display value in the list collector.

  31. Bryan August 31, 2015 at 9:39 pm - Reply

    The hiding of the filter itself no longer works in Fuji. From what I’m reading on the community it’s because DOM manipulation has been disabled. Any ideas on how to still hide the filter?

    • Bryan August 31, 2015 at 9:48 pm - Reply

      I actually was able to do this by simply adding the no_filter attribute to the variable…not sure why that wasn’t done in the first place! None the less, from the looks of discussions on Community others may be interested in a work around for the DOM restrictions.

  32. Stéphane September 30, 2015 at 5:34 am - Reply

    Hi Everyone,

    I use this script for fix a filter on list collector and hide this filter. Great Work On Eureka version!
    But Anyone have tried to hide this filter on Fuji ?
    When I apply this solution, i can’t see my filter and my list collector ?

    Anyone have fixed this issue ?

    Thanks !

  33. Simon October 5, 2015 at 9:23 am - Reply

    Hi All,,

    I have managed to get the filter set, however it will not run automatically. I have to go in, re-do the filter manually and run.

    Any help would be appreciated! 🙂

  34. Wade October 6, 2015 at 2:47 pm - Reply

    Hi David,

    Did you ever find a solution to this? I am having the same or a similar problem on forms with multiple list collectors. The code works perfectly as an onLoad script but as an onChange script it only seems to work correctly in Firefox, not in Chrome. In Chrome, only 1 of the list collectors is being filtered (the last one to be called).

  35. Matthew November 20, 2015 at 10:12 am - Reply

    Hey Mark,

    Great script.
    I’ve run into an issue. I’ve got 2 list collectors on one form. Each list collector is its own variable set. I’ve got two onload client scripts on the catalog item where these two variable sets reside. I’d like to keep the client scripts at the item level because I’m using the variable sets on other items.

    Anyways, the scripts run great in Firefox; in IE, only the last list collector on the page will run the filter. The first list collector pulls in all values w/ no filter. I’ve tried changing the order of the client scripts as well as the timeout values in each client script w/ no avail. Any suggestions?
    Thanks in advance

    • Matthew November 20, 2015 at 10:46 am - Reply

      Correction to above:
      The first list collector will pull in values; it is the 2nd list collector that pulls in all values w/out the filter applied

  36. Matthew November 20, 2015 at 11:30 am - Reply

    Found the issue
    There was a timing issue with IE. It didn’t like running synchronous calls at the same time so we wrapped the window[] lines in a setTimeout function in one of the client scripts like this:

    setTimeout(function(){
    window[collectorName + ‘g_filter’].reset();
    ….
    },1000);

    • Alvis January 22, 2016 at 2:24 pm - Reply

      Thanks Matthew, this helped a lot. Wrapping the timeout like so
      setTimeout(function(){
      window[collectorName + ‘g_filter’].reset();
      window[collectorName + ‘g_filter’].setQuery(filterString);
      window[collectorName + ‘acRequest’](null);},1000);

      helped solved my problem of filtering multiple list collectors!!

  37. Mark Sandner December 7, 2015 at 2:57 pm - Reply

    Hi Mark,
    have you ever come across a way to filter the List Collector depending on a selection in a choice list? Say you had a choice list of
    Hardware
    Software
    Applications

    and the choice was Software,
    LC filters to all software items.
    user changes choice to Hardware
    Previous items stay in Right hand side of LC
    LC filters by Hardware Items.

    Or would the LC take so long to render its not worth it.
    Many thanks, Merry Christmas
    Mark

  38. Allan Wolfe December 9, 2015 at 3:20 pm - Reply

    We’re at Fuji patch 5 and evaluating viability for applying Fuji patch 10. We’ve found that the “.style.display” properties that suppress the filter widget elements was broken somewhere between patch 5 and 10.

    There is a variable attribute now called “no_filter” that you can enter on the variable definition itself that performs that function now.

  39. Naveen January 27, 2016 at 3:43 pm - Reply

    I have tried the same code in on change function on a variable.

    //Type appropriate comment here, and begin script below
    //var collectorName = ‘df_uat_tcycle_servers’;
    var filterString = ‘u_tomcat_group=799d6e58206705486fc1cca07d6f3232’;

    //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*/
    alert(‘test’+filterString);
    //Reset the filter query
    df_uat_tcycle_serversg_filter.reset();
    df_uat_tcycle_serversg_filter.setQuery(filterString);
    df_uat_tcycle_serversacRequest(null);

    But it is working while loading the form, but after entering value in the variable the list is showing all the results..
    Do any one has idea where I am doing wrong.

  40. Ramesh March 29, 2016 at 3:13 am - Reply

    I used this script and it worked for me. Thank you so much for publishing this script.

  41. Robbie April 13, 2016 at 11:25 am - Reply

    Thanks Mark,

    FWIW, this was only working for me in Chrome. In Firefox and IE, the list collector just always says ‘loading’. I had to change the last lines:

    window[collectorName + ‘g_filter’].reset();
    window[collectorName + ‘g_filter’].setQuery(filterString);
    window[collectorName + ‘acRequest’](null);

    To:
    nameOfCollectorg_filter.reset();
    nameOfCollectorg_filter.setQuery(filterString);
    nameOfCollectoracRequest(null);

    After that, it worked in all browsers.

  42. Brandon April 27, 2016 at 11:43 am - Reply

    We found that this script doesn’t always work in Geneva. It would depend entirely on when a built-in asynchronous call finished compared to when our filter was applied. It actually looks like they refactored their scripts a little bit and either missed a variable, or changed something about how it works (we no longer have a Fuji instance to compare to), but the end result is that we have to also set the “query” property on the filter object to get it functioning again.

    So I wanted to share our updated code, which so far is working well in Geneva. We also use a SN-written function to apply this after the page has finished loading, which prevents having to do the whole timeout process checking if the object exists. Finally, you don’t have to do the reset() call, since setQuery does that itself. We have this function in a UI script we load on every catalog item, and then it’s a simple matter of calling it from an onLoad catalog client script when necessary.

    function filterSlushbucket(ctrl, filter) {
    addLateLoadEvent(function() {
    eval(ctrl + ‘g_filter.query = “‘ + filter + ‘”;’);
    eval(ctrl + ‘g_filter.setQuery(“‘ + filter + ‘”)’);
    eval(ctrl + ‘acRequest(null)’);
    });
    }

    • Yeny April 27, 2016 at 3:41 pm - Reply

      Hi Brandon, I am having a problem with this in Geneva as well. Would you be able to share your client script with me? My script is getting stuck in checking the time out and it goes on a loop.

      Thank you,
      Yeny

      • Karen May 31, 2016 at 9:11 am - Reply

        Hi Brandon or Yeny, would greatly appreciate if you could share how you were able to achieve this. We are had issues with this in Geneva and now Helsinki. Thank you!

    • Mark June 17, 2016 at 3:14 pm - Reply

      Hi Brandon,

      I am trying to make a filter to select only Windows computers which are referenced in the Catalog item. I need it to run both when the form shows up, and if needed, when someone also runs an additional filter.
      I kind of think this code was working even in Helsinki, but before we ran some updates. But I could be mistaken.
      // Not sure why this worked previously in DEV, but not now
      function onLoad() {
      //Apply a default filter to the list collector variable
      var collectorName = ‘computer’;
      var filterString = ‘osLIKEwindows’;
      //Hide the list collector until we’ve set the filter
      g_form.setDisplay(collectorName, false);
      setCollectorFilter();

      function setCollectorFilter(){
      //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(window[collectorName + ‘g_filter’]) == ‘undefined’){
      setTimeout(setCollectorFilter, 100);
      return;
      }
      //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
      window[collectorName + ‘g_filter’].reset();
      window[collectorName + ‘g_filter’].setQuery(filterString);
      window[collectorName + ‘acRequest’](null);
      //Redisplay the list collector variable
      g_form.setDisplay(collectorName, true);
      }
      }

  43. Göran Lundqvist September 6, 2016 at 10:56 am - Reply

    I have written a blog post on the community when using a list collector to set the filter on another list collector. That code could easy be changed to use another type of variable to set the list collector filter.

    You can find it here: https://community.servicenow.com/community/develop/blog/2016/09/02/filter-list-collector-with-list-collector

    //Göran

  44. Swarna September 9, 2016 at 1:08 pm - Reply

    Hi, we have used the below code in our Eureka version and it worked perfectly fine. But the same is not working when we upgraded to Helsinki. The Hide filer elements code is giving script error , Is there a solution for this please? (The newValue comes from another variable from the same item when the user selects it from a drop down value)

    • Mark Stanger September 9, 2016 at 2:16 pm - Reply

      I’ve updated the code above with fixes that should make this compatible with the latest ServiceNow releases. Please give the new code a try and let me know how it goes.

  45. Harish Gubba October 4, 2016 at 12:54 am - Reply

    Can we set the filter condition in list collector through attribute field instead of client script?

  46. Tyson Wenger February 22, 2017 at 2:18 pm - Reply

    HI Mark,

    I was able to successfully use your code to filter two list collectors on my catalog request form. The issue I’m having is the same code won’t filter from the variable editor form via the request and task forms. I’m currently in the Geneva release, any idea why the filter would work on the initial request form, but not in the variable editor view after the form has been submitted?

    Thanks,

    • Mark Stanger February 22, 2017 at 4:23 pm - Reply

      I’m not sure. In my testing it seems to work fine on a Helsinki instance for me. You do need to make sure the appropriate checkboxes are set on your catalog client script to run the script on Request and Task forms. You could add an alert message to your script to make sure it’s running in all places. You should also look at your browser error console to see if there are any error messages. Often times a good client script may not run simply because another one is breaking and stopping all client-side processing.

  47. Tyson Wenger February 23, 2017 at 8:02 am - Reply

    Thanks for the response Mark, got it figured out! I forgot to add one of the parameters on the setTimeout function. So it all boiled down to a simple typo… The joys of development 🙂

    Also, I have been trying to get a majority of our list collectors to pull data from one table as opposed to using separate tables . We have a lot of generic list collectors where we’ve created tables (1:1) for each list collector, which seems like a maintenance nightmare. That’s where your filter magic has helped.

    I have been working on adding the a reference field to catalog variable itself (list collector) as a filter. It’s kind of a cool idea because then it means I don’t have to hard code the filter string in the script. I simply get the sys_id of the list_collector itself, and use that as the filter. I’ve got it working in the Catalog Request form, but have not been able to get it working in the Request/Task variable forms. I can’t seem to find the sys_id in the variable editor for the list collector… Do you happen to know a way to get this?

    For example, from a script running on the catalog request form I do this:

    var appCollectorSysID = form.getControl(collectorName).id;

    This returns IO:ef324r92304939923 (sys_id of the list collector)

    When that same code runs on the Variable Editor, it does not return the sys_id of the list collector…

    thanks,

    -Tyson

    • Mark Stanger February 23, 2017 at 10:52 am - Reply

      ServiceNow pretty severely restricts the variable ‘g_form’ API on back-end forms. ‘getControl’ actually isn’t available there. There are some hacks you can try though. Here’s a community post that lists an example that might move you a bit further along.

      https://community.servicenow.com/thread/177647

      • Tyson Wenger February 23, 2017 at 12:06 pm - Reply

        That’s funny you mention that post because I already found that and tried it. Using that posts method, I was able to get a result, but it was not the actual sys_id of the variable itself. You could use “g_sc_form” with the getControl method.

        var form = typeof g_sc_form != “undefined” ? g_sc_form : g_form;
        var appCollectorSysID = form.getControl(collectorName).id;

        Unfortunately both methods return the same value, which is not the sys_id but must align to some other ID. Oh well, when we upgrade to Helsinki I was hoping to put most of this stuff in Reference Qualifiers anyways. Thanks for the help Mark.

  48. Lida Soileau March 13, 2017 at 11:11 am - Reply

    How can I get the value of another variable into the filter?

  49. T.H March 25, 2017 at 2:41 pm - Reply

    Hi Mark!
    Thanks for sharing. I’ve been using this solution for a while now and it works great.
    However we are currently upgrading from Fuji to Helsinki. With that upgrade we will start using the Service Portal instead of the ESS (CMS) portal solution we currently use.

    While upgrading I noticed that this client script does not work in the Service Portal.

    Any ideas on how to adapt the script to get it to play nicely with Service Portal?

    Thanks.

    T.H

    • Mark Stanger March 25, 2017 at 6:18 pm - Reply

      Get used to your client scripts being broken in Service Portal. 🙂 Fortunately, I think there’s a workaround in this case. Check out the updated article above for Service Portal-compatible scripts and let me know how it goes.

  50. Sean Bolton April 6, 2017 at 12:51 pm - Reply

    Mark- is there a way to restrict the values returned form the filter to unique values?

  51. Chandran May 24, 2017 at 1:43 pm - Reply

    Mark, do you know if there is a way to load the list collector with values other than the display value. I would love to get some other fields in there

  52. Ashish Rai Sharma June 5, 2017 at 2:26 pm - Reply

    Hi Mark,

    This code doesn’t seem to be work with the non-admin user. It works with Admin user, but when I impersonate with the non-admin user, it clears out the list. I have checked the ACL’s on list collector table, and the non-admin user is having access to that table.
    Is there something wrong with security to table?

    Thanks
    Ashish

    • Mila Morales September 19, 2017 at 1:26 pm - Reply

      Hi Ashish,

      I’ve tested this script to a Catalog item and impersonates a users without any role, I created a new record using the catalog item with a list collector run the script using a client script and it works as I expected. Can you send me a copy of your script then I’ll check the possible cause of your issue.

  53. ram June 13, 2017 at 1:05 pm - Reply

    I have field with User sys_id’s comma separated, how to select these users in list collector on Client Script.

  54. Nitin Kumar August 28, 2017 at 11:21 pm - Reply

    Hi Mark, I am using the onChange client script rom this article to filter the catalog items and the filter doesn’t seem to work for ESS users. Do you have any idea why?

    • Mila Morales September 6, 2017 at 1:24 pm - Reply

      Actually this would work whether a user has role or not. You can send a copy of your script then we’ll check the problem.

  55. Pritesh Prajapati September 13, 2017 at 8:47 am - Reply

    Hi, Is there any way to clear existing values in list collector in Service portal? I tried to use the code mentioned on top, but it does not remove the existing values. It refreshes list collector filters only.

Leave A Comment