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.
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.
//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);
}
}
//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);
}
}
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
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.
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?
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.
Hi Mark,
just tested it on demo, (dev laptop item)
name of filter is “filter”
still not working
Alli
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
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).
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.
Thank you! That script is perfect!
Mark
Thanks for the help. The delay was the trick I needed to get the filter to load correctly.
Awesome Mark…Thanks!
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
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.
The sys_id worked like a dream. I didn’t try getDisplayValue. Thank you.
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?
You should be able to hide the information below the list collector in a client script like this…
If that doesn’t work, then you can customize the fields below a slushbucket for that table like this…
https://servicenowguru.wpengine.com/system-ui/customizi…
And you could potentially set up ACLs to hide the data you don’t want to be seen too.
Aha, gel(‘YOURVARNAMEHERErecordpreview’).hide(); worked!!! Thanks Mark
Mark, hey this method works as expected in Chrome but not in IE 10 in IE7 Standards Mode. Suggestions? Gracias in advance….
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.
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.
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, 🙂
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.
hi,
this solution does not work on firefox. is there a work around for this?
thank you,
sandy
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.
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.
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);
}
}
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.
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.
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);
}
Cool. Thanks for sharing your solution!
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:
document.observe('dom:loaded', setMyFilter);
}
function setMyFilter() {
...
}
Or the anonymous approach:
document.observe('dom:loaded', function() {
// set filter here
});
}
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.
Mark,
The functional equivalent using ‘Event.observe’ syntax for what I coded would be:
...
});
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
in jQuery.
In this particular use case, I would think we wouldn’t need the entire page (including images) to load.
John
No particular reason. Just the convention I’m used to.
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
Great Article. Works like a Charm! Thanks.
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
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…
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
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
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…
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.
You need to personalize the dictionary for some field in that table and check the ‘Display’ checkbox.
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?
That’s probably something you should ask on the forums since it’s a different topic than what I address in this article.
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.
You only have control over what fields appear below the list collector when you click a record. See this post for details.
https://servicenowguru.wpengine.com/system-ui/customizing-slushbucket/
Hey Mark,
Is there a way to apply the filter to the right box in list collector?
There’s not a way that I’m aware of to do that.
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.
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.
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 ?
Hi Peter,
Unfortunately I think you’re stuck with what you see in that filter. That whole page isn’t really customizable at all.
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
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.
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.
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.
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.
@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!
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?
There’s no way that I’m aware of.
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:
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);
}
Cool Steve! Thanks for sharing.
This is great help, this is working perfectly for me thanks a for sharing such codes 🙂
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?
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.
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
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?
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.
Is there a way to sort the filtered list? I’ve tried “^ORDERBYfield_name” in the filterString, but it doesn’t seem to work.
There isn’t currently a way to sort the results of a list collector.
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?
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.
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.
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).
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;
}
Nice! Thanks for sharing.
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.
There isn’t. You can only see the display value in the list collector.
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?
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.
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 !
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! 🙂
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).
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
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
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);
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!!
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
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.
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.
I used this script and it worked for me. Thank you so much for publishing this script.
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.
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)’);
});
}
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
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!
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);
}
}
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
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)
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.
Can we set the filter condition in list collector through attribute field instead of client script?
Unfortunately, no.
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,
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.
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
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
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.
How can I get the value of another variable into the filter?
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
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.
Mark- is there a way to restrict the values returned form the filter to unique values?
Not that I’m aware of.
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
Here’s a link that can help:
https://servicenowguru.wpengine.com/system-ui/customizing-slushbucket/
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
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.
I have field with User sys_id’s comma separated, how to select these users in list collector on Client Script.
Hi Ram,
Our article entitled Move List Collector Options may give you some ideas.
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?
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.
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.