Filter list view based on membership in SharePoint group

This script filters a list view based on membership in SharePoint groups. The filtering has nothing to do with item level security, it is merely a method for filtering by comparing a users group membership against a text field containing a group name. This column “VisibleTo” must contain the actual group names from the “People and Groups” list in SharePoint.

This method gives you the ability to filter the list view based on multiple criteria. If the user is member of multiple groups, the list will display all items relevant to any of the groups. You may also specify that elements where the column “VisibleTo” is empty will be displayed for all visitors. The “VisibleTo” column can be a multiple choice checkbox type column.

As always we start like this:
Create a document library to hold your scripts (or a folder on the root created in SharePoint Designer). In this example i have made a document library with a relative URL of “/test/English/Javascript” (a sub site named “test” with a sub site named “English” with a document library named “Javascript”):
IMG

The jQuery-library is found here. The pictures and the sourcecode refers to jquery-1.3.2.min. If you download another version, be sure to update the script reference in the sourcecode.

The scripts “interaction.js” and “stringBuffer.js” is created by Erucy and published on CodePlex.

The script “AccessUserProfileInWSS.js” is found here.

Note:

  • If used in grouped views, you must have the groups initially expanded, otherwise the elements are not rendered and cannot be filtered.
  • Only one level of grouping is currently supported.
  • Boxed view are not supported.
  • The filter does not apply in a datasheet view.

Add a CEWP below the list view webpart, and add this code:

<script type="text/javascript" src="../../Javascript/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="../../Javascript/interaction.js"></script>
<script type="text/javascript" src="../../Javascript/stringBuffer.js"></script>
<script type="text/javascript" src="../../Javascript/AccessUserProfileInWSS.js"></script>
<script type="text/javascript" src="../../Javascript/FilterListViewByGroupMembership.js"></script>
<script type="text/javascript">

// Find the user login name
var ui = getUserInfo(); 
var userLoginName = ui['Name'];
// Get the group collection for the current user
var ug = getGroupCollectionObjFromUser(userLoginName);
// Set the filter - if you want the results to include elements in a specific group by default, specify it in the array below
filterVal = [];
// Define the group - find the group ID in "People and Groups"
var groupIdTeam1 = 145;
var groupIdTeam2 = 146;
// Build the filter - add more if's to complete your filter
// Is the user member of the group with id 145?
if(ug[groupIdTeam1]!=undefined){
	filterVal.push(ug[groupIdTeam1]);
}
// Is the user member of the group with id 146?
if(ug[groupIdTeam2]!=undefined){
	filterVal.push(ug[groupIdTeam2]);
}

// Call the function
filterListViewByGroupMembership('VisibleTo',filterVal,true,true,true);
</script>

The sourcecode for the file “FilterListViewByGroupMembership.js”:

/* Filter list view by membership in SharePoint group - hide the column header and the filter column if specified
 * -----------------------------
 * Created by Alexander Bautz
 * LastMod 15.02.2010
 * -----------------------------
 * Include reference to:
	jquery - http://jquery.com
	interaction.js - http://spjslib.codeplex.com/
	stringBuffer.js - http://spjslib.codeplex.com/
	AccessUserProfileInWSS.js
	FilterListViewByGroupMembership.js
 * -----------------------------
   If used in grouped views, you must have the groups initially expanded, otherwise the elements are not rendered and cannot be filtered.
   Note: only one group level is currently supported.
*/

function filterListViewByGroupMembership(FieldInternalName,filterValueArr,includeEmpty,hideFilterCol,collapseGroupedViews){
filterOK = true;
	// Build object of all headings
	if(typeof(filterColIndex)=='undefined'){
		if(typeof(FieldInternalName)=='string'){
			intName = FieldInternalName;
			hideTD = hideFilterCol;
			fvArr = filterValueArr;
			inclEmpty = includeEmpty;
		}
		filterColIndex = '';
		$(".ms-viewheadertr th").each(function(){
			if($(this).find('table:first').attr('name')==intName){
				filterColIndex = $(this).attr('cellIndex');	
				displayName = $(this).find('table:first').attr('displayname');
				// If the parameter "hideFilterCol" is true, remove the column
				if(hideTD){
					$(this).remove()
				}
			}
		});
		
		if(filterColIndex==''){
			filterOK = false;
			var str = "<font color='red'>The column with FieldInternalName  "" + intName + "", must be in the view for the filter to work.</font>";
			$("td.ms-toolbar[width='99%']").append("<div id='hoverDelayInfo' class='ms-listheaderlabel' style='text-align:center;margin-top:-15px'>" + str + "</div>");
		}
	}
	
	// Apply filter
	if(filterOK){
		// Build view header text
		if(inclEmpty && fvArr.length==0){
			fvArr.push('');
			var fv = displayName + " = empty";
		}else if(inclEmpty && fvArr.length>0){
			fvArr.push('');
			var fv =  displayName + " = " + fvArr.join(' or ') + " or empty";
		}else if(!inclEmpty && fvArr.length==0){
			var fv = "No filtervalues found - all items hidden";
		}else if(!inclEmpty && fvArr.length>0){
			var fv =  displayName + " = " + fvArr.join(' or ');
		}		
		// Insert view header text
		if($("#filterInfo").length==0){
			$("td.ms-toolbar[width='99%']")
				.append("<div id='filterInfo' class='ms-listheaderlabel' style='text-align:center;margin-top:-15px'>" +
						"<span style='cursor:default'><img src='/_layouts/images/filter.gif'> " + fv + ".</span></div>");
		}

		// Find all rows and apply filter
		$("table.ms-listviewtable tbody:not([id^='aggr']) tr:has(td.ms-vb2) >td[cellIndex=" + filterColIndex + "]").each(function(){	
			var thisTd = $(this);
			// Build array from all values in "Visible to" - column
			var arrCurrTDtext = thisTd.text().split(';');
			var keeper = false;
			// Find all keepers
			$.each(arrCurrTDtext,function(i,val){
				var thisVal = $.trim(val);
				if($.inArray(thisVal,fvArr)>-1){
					keeper = true;
				}
			});	
			// Remove the ones that do not match
			if(!keeper){
				thisTd.parents('tr:first').remove();				
			}			
			// If the parameter "hideFilterCol" is true, remove the column			
			if(hideTD){
				$(this).remove()
			}
		});
		
		// Test whether the view is grouped twice and give alert
		if($("td.ms-gb2").length>0)alert("Sorry, but this script does not handle views grouped twice.");
		// Loop trough every tbody to remove empty and to update item count
		$("tbody[isloaded='true'][beenthere!='true']").each(function(){
			$(this).attr('beenthere',true)
			var gId = $(this).attr('id');
			var gIdPart = gId.substring(4,gId.length-1);
				// Number of elements remaining
				var trLength = $(this).find("td.ms-vh-group").length;				
				if(trLength==0){	
					// Remove the group heading and remaining elements for the group			
					$("#titl"+gIdPart).remove();
					$("#foot"+gIdPart+"_").remove();
					$(this).remove();
				}else{
					// Write the new count to the group heading
					$("#titl"+gIdPart).find('td.ms-gb span:last').html("‎(" + trLength + ")");
				}
		});
		
		// Collapse all groups - they must be expanded by default for the filter to apply
		if(collapseGroupedViews){
			$("td.ms-gb").each(function(){
				$(this).find('a:first').click();
			});
		}
		
		// Fix highlighting of every other row
		var classToFind = '';
		if($("table.ms-listviewtable").find('tr.ms-alternating').length>0){
			var classToFind = 'ms-alternating';
		}else if($("table.ms-listviewtable").find('tr.ms-alternatingstrong').length>0){
			var classToFind = 'ms-alternatingstrong';
		}
		if(classToFind!=''){
			$("table.ms-listviewtable tr:has(td.ms-vb2)").each(function(i,row){
				if(i%2==0){
					$(this).addClass(classToFind);
				}else{
					$(this).removeClass(classToFind);
				}
				
			});
		}
		
	}
}

/*
 * Function to get the groupCollectionfrocurrent user.
 * Requires the scripts interaction.js and stringBuffer.js to be loaded
*/
function getGroupCollectionObjFromUser(userLoginName){
	var result = {};
	innerPost(wsBaseUrl + 'usergroup.asmx', 
		'http://schemas.microsoft.com/sharepoint/soap/directory/GetGroupCollectionFromUser',
		'<GetGroupCollectionFromUser xmlns="http://schemas.microsoft.com/sharepoint/soap/directory/"><userLoginName>' + userLoginName + '</userLoginName></GetGroupCollectionFromUser>',
		function(data){		
			$('Group', data).each(function(idx, itemData){
				result[$(itemData).attr('ID')] = $(itemData).attr('Name');
			});
		});
	return result;
}

// Attaches a call to the function to the "expand grouped elements function" for it to function in grouped listview's
function ExpGroupRenderData(htmlToRender, groupName, isLoaded){
	var tbody=document.getElementById("tbod"+groupName+"_");
	var wrapDiv=document.createElement("DIV");
	wrapDiv.innerHTML="<TABLE><TBODY id="tbod"+groupName+"_" isLoaded=""+isLoaded+"">"+htmlToRender+"</TBODY></TABLE>";
	tbody.parentNode.replaceChild(wrapDiv.firstChild.firstChild,tbody);
javascriptFilterView();
}

Save as “FilterListViewByGroupMembership.js”, mind the file extension, and upload to the scriptlibrary as shown above.

Let me know if something is unclear.

Regards
Alexander

39 Comments on “Filter list view based on membership in SharePoint group

    1. Hi,
      I have not yet made any solutions that can do this, but i have some ideas on how it could be done. Please post a request in the Request’s post with the details on how the filter is supposed to work, I will then add it to the “article queue”. I cannot however promise any “delivery date”.

      Alexander

    2. Thank you again for speedy reply. I will post my request in the request post. Ofcourse I understand you can’t promise any delivery date.

      Thx for the the trouble anyway.

    1. Hi,

      thanks it worked. may problem now is my view has paging, and sometimes the record for a user doesnt display not unless i click on the paging link. think it still retains the current sorting of records

    2. Hi,
      This has to do with the fact that this filter is applied after the “original” items are rendered in the browser. If you have paging configured, you might set the “Item limit” to 20, but if none of this 20 items fit the javascript applied filter, the list will be empty.

      I do not have any other solution than removing the “paging” option – or use the “Current user filter” found in MOSS 2007 (if you have MOSS).

      Alexander

  1. Hi,
    Thanks for this article! Quick question? Will this work on a list which is used in a form? I sort of think it will not because the CEWP is rendering on the page, but how could it affect a form?
    Any thoughts? Thanks in advance!

    Tracey

  2. Excellent work! I have a question though. It only work with one “Group by” choice. How do you add additional Group by fieled or choice?

  3. Hi,

    great article. I am trying to implement this. I got the userName correctly.
    But, it seems to be failing at this line.

    var ug = getGroupCollectionObjFromUser(userLoginName);

    After the above call, I am expecting the ug variable to contain something. if I check the length using ug.length, it is returning undefined.

    any idea?

    How do I get the groupID to be used here?

    Many thanks,

    Anu

    1. Hi,
      The variable ug is an object and has no “length”. You find the groupId in the “People and Groups” section in SharePoint. Go to the desired group and look at the URL and you will find the groupID like this:
      …/_layouts/people.aspx?MembershipGroupId=3

      Alexander

  4. Hi, great bit of code. It works brill on a standard list view, but i’m trying to use it on a web part page with the list in the body and some other links on the right hand column, and it doesnt filter at all. Any ideas?

    1. Ah, good to see it’s not just me then. I’m a complete newbie on both java and sharepoint (ok at VBA!), but i’ll have a look through your tips and see if I can make head or tail of the code!

      Thanks for all the great stuff on this site

  5. I think in function getGroupCollectionObjFromUser(userLoginName) on line number:
    143 var result = {};
    is an error. Shouldn’t it be like this
    143 var result = []; ??
    Then You can use returned object(var result) as an array and then it has length property.

    1. Hi,
      Sorry, but the function “getGroupCollectionObjFromUser” is supposed to return an object literal and not an array.

      The variable “ug” in the CEWP code is an object and when you “ask” the object for its value for the property “group ID of your group”, you get the groupname.

      Alexander

  6. Hi Alex, will this method of filtering be supported in SP2010; I tried it on a SP 2010 list and it does not work; are there changes I need to make for this to work. Thanks

    1. Hi,
      The HTML is different from 2007 and the script would have to be modified to work. Another matter is that the view is updated/drawn asynchronously.

      This will require the handling of grouped views to be different as the code must keep running at timed intervals to check whether the view have changed.

      I cannot promise that this script will be “ported” to SP2010.

      Alexander

  7. If I could get this to work it would be exactly what i need I am still New to JavaScript and SharePoint.
    For this Section Should I full qualify this since it is on the SharePoint site like below

    For the Section If my groupIdReam1 was bobs_team and the ID was 123 Would every Were groupIdTeam1 show up need to be updated to B
    // Define the group – find the group ID in “People and Groups”
    bobs_team or leave it alone and update the ID like this var groupIdTeam1 = 123;

    var groupIdTeam1 = 145;
    var groupIdTeam2 = 146;

    Thanks

  8. Unfortunately the link downloads a file that is of no use. The scripts “interaction.js” and “stringBuffer.js” is created by Erucy and published on CodePlex. Can you provide a better link?

    1. Hi,
      Go to the People and Groups page, click on your group and look at the URL for the ID parameter.

      I think this should also work in 2010.

      Alexander

    1. Yes, but it will need some modifications. From the file “FilterListViewByGroupMembership.js” you need only the function “getGroupCollectionObjFromUser”.

      In the CEWP code you will have to write the logic for which option to show for each group and loop trough the options in the dropdowns – hiding the ones that does not apply.

      See what you can make out of it. Ask if you need any more guidance.

      Alexander

      1. When I add the CEWP, it removes the “Views” altogether. I have the ID correct. I’m in the same boat where I just want specific views to be in the view drop down list. How would I go about creating this list? Ex: view named ABC.aspx and DEF.aspx???

        As you can see, I’m a little new to jQuery. I have some exposure to javascript. I’ve been able to get the CEWPs to work that I’ve tried, except this one so far.

  9. Hi –

    My test user, who is a member of a group selected from the VisibleTo column keeps getting prompted for her login information.

    And the items in the list where she has selected the proper group actually will not display for her – so it’s kind of working backwards!

    I’m sure I have something bolloxed up – any ideas? Any help will be appreciated.

    1. Hi,
      This solution has nothing to do with user rights. It’s only a method of filtering items from the view if the user is not a member (again – no rights, only member or not) of a given group.

      Alexander

  10. Hi Alex,

    Great post! I know you mentioned this only works on a native view but I wanted to know if you can apply the same concept for users to have certain views based on membership group?

    For example, I have the standard AllItems view but I also have four other views that I created. What I would like is for certain groups to have access to specific views that were created.

    Currently I have had to have different groups create personal views individually to make this happen but it would be great if we could create a public view as an administrator and have only certain group have access to that view.

    Any help would be greatly appreciated.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.