modery.net

Providing Filter Dropdowns for a SharePoint List/Library with jQuery

Let’s say your users want to have an easy way to filter items in a SharePoint list or library, but for some specific reason they should be able to do this with some other functionality than the standard filtering made available in the list&library column header. With a little help of jQuery and SPServices you can easily achieve this and add some dropdowns onto a page, and you can even easily add a nice design (though I’ll leave this part out of this article and leave it up to you to implement with some CSS).

 


What we want to achieve

The following screenshot shows how this solution allows you to apply filters to a list similar to the way these standard column header filters work. As you can see, filters for the columns SingleLineOfText and Number have been applied already, I could also apply another filter for Currency.

Image(1)

You have the choice which columns you want to be filterable here. If you have 5 columns (Name, Address, ZIP, City, Country), you could supply filters for 2 columns (City, Country) only!

The benefit of this solution here is that it works anywhere. For example, you can use it in combination with a Data View Web Part instead of the standard list/library Web Part (Edit: DVWP work differently than the “normal” list/library web parts; I’m currently testing how to integrate this solution with them). Another option would be to provide users with nicer looking filter dropdowns somewhere else on the page (on top of the library; to the right; embedded within some descriptive text!; etc).
Also, this is probably the easiest way to get a dropdown of all possible unique filter values.

 


Background Information

The filters here do not recreate the standard filter menus, but rather reuse SharePoint’s very own creation mechanism (the same way that these standard menus are created). Basically, the filter menu for a list/library is created through JavaScript. You can find the relevant function addFilterMenuItems in the core.js file . Diving into its functionality, once can see that SharePoint actually calls the file /_layouts/filter.aspx when creating the filter menus. If you open this page manually with the relevant parameters, you get to see that it creates a dropdown just the way we need it:

Image(2)

An example for this URL is:

http://myserver/mysubsite/_layouts/filter.aspx?ListId=%7B8A624345%2DDB60%2D41E6%2D9863%2D3DAF60557DA1%7D&FieldInternalName=Region&ViewId={CDBA0419-769D-4AFB-9152-6D311DE99879}&FilterOnly=1&Filter=1

These relevant parameters are:

  1. the ID of the list/library that you’re using (ListId)
  2. the ID of the view that you’re using (ViewId)
  3. the name of the column that we want to filter (FieldInternalName)

Information about how to find all these parameters is listed further below in this article.

It is also important to note the following things:

  1. If one or more filters are applied, all other filters will take them into account. If I filter by Number in my example above, the dropdown for Currency will only show me the values for those rows which meet the Number filtering as well.
  2. If SharePoint doesn’t allow you to filter a field (e.g. multiple lines of text), you can’t filter it here

The important question is: how do we get the values from this dropdown onto our page?

In the discussion board of SPServices you can find a thread that briefly discusses how to retrieve the dropdown itself as well as it’s values. With some modifications, this code can be used for our solution.

 

The Code

The code below consists of two parts, a JavaScript section (including jQuery and SPServices usage) to retrieve the dropdown and prepare its output as well as a simple HTML section where we present the result of the JavaScript code.

//update the following 2 lines with your own local versions if wanted
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2014.01/jquery.SPServices.min.js"></script>
<script type="text/javascript">
$("document").ready(function() {
//set default vars; replace them with your ownvar
listID = '{B858515E-A827-4444-98DA-E81B4F1AF0AD}';
var viewID = '%7B3C11FBF2%2D9702%2D4B76%2DB280%2D02A783B8E7FA%7D';
//load paramsvar
allVars = $().SPServices.SPGetQueryString();
var filterFieldsParams = "";
$.each(allVars, function( objKey, objValue ){
if(objKey.substr(0,11).toLowerCase()=="filterfield" || objKey.substr(0,11).toLowerCase()=="filtervalue"){
filterFieldsParams+="&"+objKey+"="+objValue;
}
});

function getAjaxFilter(name, internalName){
$.ajax({
url: $().SPServices.SPGetCurrentSite()+'/_layouts/filter.aspx?ListId='+listID+'&FieldInternalName='+internalName+'&ViewId='+viewID+'&FilterOnly=1&Filter=1'+filterFieldsParams,
success: function(data) {
// replace"<b>"+name+": </b>" with your own code if required
$('#filterField'+internalName).html("<b>"+name+": </b>").append($("<div></div>").append(data).find("select, img"));
//clear current onChange event
$("#diidFilter"+internalName).attr("onchange", '');
// add change event
$("#diidFilter"+internalName).change(function() {
FilterField(viewID,internalName,encodeURIComponent(this.options[this.selectedIndex].value), this.selectedIndex);
});
}
});
}
// provide selected filters
getAjaxFilter("Single Line of Text", "SingleLineOfText");
getAjaxFilter("Number", "Number");
getAjaxFilter("Currency", "Currency");
});
</script>
<div id="allFilters">
<div id="filterFieldSingleLineOfText"></div>
<div id="filterFieldNumber"></div>
<div id="filterFieldCurrency"></div>
</div>

 


Explanation

The first two lines load the necessary jQuery and SPServices scripts. In the beginning of the JavaScript code block, we first define the ID of the list/library and the view, and then to fetch any filter parameters that may have been applied already from the URL. In such a case, we want our filters to take into account any existing filters, so that unrealistic filter options are not shown (as mentioned under Background Information).

The function getAjaxFilter is the core of this solution. It calls the above mentioned filter.aspx page and fetches its data, filters it to return only any dropdown and any images (if a filter is applied, an icon is shown), and updates the dropdowns onChange event. The reason for this is that the default behaviour in this case doesn’t work properly when you want to remove a filter (when you select (All) from the dropdown). What we need to do here is to simply call the exact same JavaScript function FilterField (defined in core.js) with the correct parameters.

After the function declaration, we have 3 function calls, which you will later need to r
eplace with your own. Lastly, there are three named DIVs which are used later to “store” the results from the getAjaxFilter calls. They follow the naming convention filterFieldINTERNALFIELDNAME, so you need to update them accordingly with your own column names (see below for how to find them out).

 


Using it on your own page

As mentioned above, there are multiple ways how you can include this solution on your page. The easiest way is to add a Content Editor Web Part (CEWP) and paste the code into its Source Editor.

What you’ll need to apply it to your own list/library is the ID of it as well as the ID of the view that you’re using. Both IDs can be in either of the following two formats:
%7BB858515E%2DA827%2D4444%2D98DA%2DE81B4F1AF0AD%7D
or
{B858515E-A827-4444-98DA-E81B4F1AF0AD}

How do you get both required IDs? When you open the settings page of the list/library, you can find its ID as part of the URL:

Image(3)

An easy way to get the ID of the view that you’re using is to apply a filter through the list/library’s header row. Afterwards you can find the ID as part of the URL:

Image(4)

To get the internal name that is used for a column, go to the list/library’s settings, and click on the column name. The internal name can then be found as part of the URL as the parameter Field:

Image(5)

Please note that if you used certain special characters while creating the column, SharePoint will not use them for the internal name, but replace them with hex codes (http://abstractspaces.wordpress.com/2008/05/07/sharepoint-column-names-internal-name-mappings-for-non-alphabet/):

Image(6)

You will still need to bring these columns into a more readable format. For example, if you copy the name marked here (My%5Fx0020%5F1st%5Fx0020%5FTest%5Fx0020%5FColumn%5Fx0021%5F), and decode it at http://meyerweb.com/eric/tools/dencoder/, you will get the actual proper name My_x0020_1st_x0020_Test_x0020_Column_x0021_ which needs to be used

Once you have all these, replace the IDs in the code with your own, and create your own DIV wrappers and getAjaxFilter calls for your respective columns.

 


Possible Improvements

There are still some improvements that could be done. Depending on your own requirements (for example if you wish to reuse that code in multiple locations), you may want to consider calling getAjaxFilter with filterFieldsParams as parameter to avoid relying on it as a global variable. Also, this implementation is not flexible when it comes to creating output in different layouts. If you want to have different ways of displaying the filters (in a table row / with different style sheets / etc), I’d recommend to not do any output changes (namely the $(‘#filterField’+internalName).html(..) call), but rather return the result from getAjaxFilter and use it in your own function for further changes.

 
Comments

Does it work for multi value column, for example multi-people. Thanks

Hien, I’ve tested it with Checkboxes as well as with a People column that allows multiple selections, it works for both. Generally I would say: if you can filter it with SharePoint directly, it works here (as I’m just reusing SharePoint’s own functionality)

I can’t add this to my sharepoint 2010 site, can u help me?
this is the error..

Mensaje: Permiso denegado
Línea: 2
Carácter: 3238
Código: 0
URI: /whc/WHCLibImg/jquery-1.7.1.min.js

Hi Javier,
I would suggest that you use the non-minified version of jQuery, and use a JavaScript debugger (e.g. the Internet Explorer Developer Tools) to find out exactly where that error occurs.
Right now I am as clueless as you about what’s happening and why

Hi I need help on setting up a web part page quickly. Can email me?
Thanks

I have followed to the best of my ability the instructions as outlined here. The result I get is a blank “Content Editor Web Part”. Is there something key that I am missing that would result in a blank web part?

Hi Spencer,

did you paste the code directly into a CEWP? If so, some of the code may have been stripped out by SharePoint. It’s better to put the code into a file, upload that file to SharePoint, and reference it from the CEWP’s properties.

If you did that already, I don’t have any immediate idea why it doesn’t work. You could try to troubleshoot by checking if the URL get from “$().SPServices.SPGetCurrentSite()+’/_layouts/filter.aspx?ListId=’+listID+’&FieldInternalName=’+internalName+’&ViewId=’+viewID+’&FilterOnly=1&Filter=1′+filterFieldsParams” is available (wrong internalname, viewid, and/or listid would probably results in an empty page, thus an empty CEWP)

A couple comments and then a quick question.

Line 5 of your code, at the end (ownvar\) that \ causes issues with the code because it still thinks line 6 is commented out. If you delete that \, it will not cause issues with line 6 and the code will be able to read the listID.

I struggled with this code for a while because I too was getting a blank CEWP even though I copied the code and replaced the proper areas correctly. When I did a JavaScript debugger, I found the issue – line 26 is missing a { at the end of the line. It should read .change(function() {

Once I added that, everything worked properly. Hopefully that helps out others who might have issues.

My question is concerning DVWP. You mentioned early in your post that you are testing how to integrate the solution with DVWP. Have you figured that out yet? I have a client that wants this exact functionality but utilizing the DVWP. Any updates or suggestions?

Thanks for your help and thanks for providing this solution.

Hi Kris,

thanks a lot for that detailed and helpful comment! Not sure where those errors came from ( I copied & pasted from working code), just corrected the code above.

As for the DVWP, I cannot remember at all how far I got. I think I haven’t touched the code above in more than a year, and I can’t remember what I meant with “the DVWP is different”. So, I don’t have any working solution or even an advise right now.
Sadly, I also won’t have time to look into it in the next few weeks (a few other things on my plate, plus going to the SharePoint conference in Vegas in November), so I have to say that I can’t help you any further right now.

Hi Rene,

Although this is a post of > 2 years old I think it could be still very useful for me.
Unfortunately I cannot get it up and running in SharePoint 2010. I get a Jquery permission denied error on line:
$(‘#filterField’+internalName).html(““+name+”: “).append($(“”).append(data).find(“select, img”));

It seems that it has problems appending the contents of ‘data’ to the div. When I use Fiddler and I check the raw response I do see the complete contents of the filter.aspx including the inline JavaScript functions, HTML etc. So apparantly it is not able to append the content of the dropdownlist to my div.
Do you have any idea how to resolve this?

Thanks in advance!

Koen

Hi Rene,

Problem solved.
Used JQuery’s parseHTML and appended it to the div so more a Jquery related question.

Regards,

Koen

Hi Koen,

glad that you managed to find a solution for your issue, and many thanks for sharing it here! I’ll have a closer look at it soon to see if including it generally in my code above might help others as well.

Rene

RT @sympmarc: Providing Filter Dropdowns for a SharePoint List/Library by @modery http://t.co/B7ZBThZ3Fx

Rene,

Nice script you got there.

Listen, I’ve made it work just fine on my server. I have quite a few filters I’d like to add though, and not all of them follow the same format. The first one was easy, it was a Select. How would I go around to add some additional filters in Date format, Checkbox and Text?

Thanks

I’ve been searching for how to do this type of thing for a while, and was so glad to find your explanation. Easily the most thorough and helpful walkthrough. My only doh! moment is that I hadn’t updated the reference to jQuery and SPServices, or changed the id of the div. Perhaps adding some comments to those sections in your code to remind us? ;)

Also, if this can help anyone else, a quick way of referencing jQuery and SPServices is to use CDN method. So top two lines of Rene’s code would be:

Also, in later versions of SharePoint consider using the Script Editor webpart instead of Content to ensure SharePoint doesn’t reformat it.

Keep up the great work!

Updated the references to jQuery and SPServices to use a CDN, as suggested. Thanks for commenting!

Hi Rene,

Love your solution. I am facing a small issue though. if the List column contains values that have & in it it filters on the string prior to &.

For e.g if list contains P&G and I filter on that, the dropdown box just shows ‘P’. Is there a way to overcome this?

Hi Jeff, fixed the code above. The call to the FilterField function now includes an encoded version of the value to filter (via encodeURIComponent). Let me know if this works for you or if there are any other issues

hi Rene,

Your postings help a lot in my work. I wanted to do multiple values and wildcard filter, however couldn’t figure out how do that with your sample. Any advice?

Thanks.

hi Rene,

I saw in core.js, the filterfield function has some coding for “filterop” which could be very useful in filtering. “filterop” like “Eq”, “Neq”, “Geq”, etc. However i couldn’t figure out how to pass “filterop” with the filterfield function.

Have you see this part of the coding?
Thank you.

Leave a Reply