SharePoint 2013 People & Groups field as a dropdown with predefined choices

If you are in the SharePoint consulting business, by no doubt you have already heard the following customer requirement:

We need a SharePoint field, which allows the user to pick one of the few predefined groups we have defined there

That’s not possible out of the box, although possible with some custom development. There is many different options here, but the one I recommend and I find it to be a ‘best practice’, is the Field JSLink approach.

Below I will show you how to implement a JSLink, which changes the People & Groups field from this:

1

to this:

2

Ok, first thing first, you probably already have somewhere in your project the definition of the Field. Something like:


You need to add JSLink attribute to it. So:

JSLink="~site/SiteAssets/jquery-1.11.3.min.js|~site/SiteAssets/JSLink/MyCompany.JSLink.Fields.GroupsAsDropdownTest.js" />

You will find the full source code of the JSLink at the bottom of the post, but let’s quickly go over it.

First, we have the standard

SPClientTemplates.TemplateManager.RegisterTemplateOverrides(FieldCtx);

which tells SharePoint to use our custom JavaScript functions to render the field in the different display modes (Edit, New, etc).

Let’s review the function which renders the field in New/Edit mode, as it is the most interesting one. What it basically does is, render the field as SharePoint would render it OOB:

var html = jQuery(SPClientPeoplePickerCSRTemplate(ctx));
html.hide();
 
return html.outerHTML() + dropdownHTML;

but hide it, and next to it render our custom dropdown list, which is driven by the configuration specified in

Fields_Renderer.DropdownOptions

Important note: the groups listed in this structure should be valid ones!

Whenever the value in the custom dropdown list changes, we run the following function:

Fields_Renderer.SelectionChange

which uses the standard SharePoint people picker functionality to clear the current value in the hidden OOB people field and set a new one (defined as value attribute in the dropdown option).

In summary:

We use JSLink on the People & Groups field to hide the standard field control and render a custom dropdown next to it. Whenever the dropdown changes, it updates the value in the hidden OOB field. When the user presses ‘Save’ on the form, SharePoint persists the user field as it normally would.

Here is the source code:

https://github.com/hyankov/PeopleAndGroupsAsDropdown

Happy coding!

Advertisements

When using [TaxonomyField].SetFieldValue you get ‘set AllowUnsafeUpdates to true’ exception

In some situations (such as ajax requests and other non-postback methodologies), you might encounter the following error:

Updates are currently disallowed on GET requests.  To allow updates on a GET, set the ‘AllowUnsafeUpdates’ property on SPWeb

This might happen if you are trying to set a Term type of object in an SPList item’s field. e.g.:

SPListItem myItem = … ;

Term myTerm = … ;

var taxonomyField = myItem[“MyTaxonomyField”] as TaxonomyField;

taxonomyField.SetFieldValue(item, term);

myItem.Update();

If you execute this in the backend during an ajax request (or maybe some other use cases too) this will fail with the exception mentioned above.

If you are reading this article it means that  you have already set the SPWeb’s AllowUnsafeUpdates to true and the problem still persists. For some reason this is the default SharePoint behavior and it doesn’t matter how many times you set the AllowUnsafeUpdates to true, it will still be ignored. So, we need another solution.

You might be tempted to use a solution (1, 2) such as setting a TaxonomyFieldValue to the field, instead of Term directly. Such as:

string termString = String.Concat(thisYear.GetDefaultLabel(1033), TaxonomyField.TaxonomyGuidLabelDelimiter, thisYear.Id);

TaxonomyFieldValue tagValue = new TaxonomyFieldValue(string.Empty);
tagValue.PopulateFromLabelGuidPair(termString);
oField.SetFieldValue(i, tagValue);

 

That would be a mistake because such approach breaks the Search Crawl (i.e. the crawler won’t crawl your field properly). So what is the correct solution? As crazy as it might sound, it is to set the HttpContext.Current to null just prior to setting the term field and then restoring it back.

So, solution:

var httpContext = HttpContext.Current;

HttpContext.Current = null;

SPListItem myItem = … ;

Term myTerm = … ;

var taxonomyField = myItem[“MyTaxonomyField”] as TaxonomyField;

taxonomyField.SetFieldValue(item, term);

myItem.Update();

HttpContext.Current = httpContext;

 

What does this achieve? It lies to SharePoint that you don’t have a HttpContext (i.e. you are not triggering this code from the browser), so it won’t validate your context and won’t throw an exception about AllowUnsafeUpdates.

 

Best Regards,

Hristo