JavaScript, SharePoint

Javascript and Working with the SharePoint 2013 People Picker

The People Picker in SharePoint 2013 has had a bit of a face-lift.

The ‘Verify Address’ and ‘Address Book’ icons are gone and what’s left is a cleaner, simpler interface.

But new controls means that some of the older approaches to working with the People Picker no longer work.

As usual I’m working with SharePoint 2013 on the client side (CSOM) working with JavaScript and jQuery.

Here are some of the results that I’ve found

Selecting the People Picker

SharePoint builds MOST of its controls using the Field’s Internal Name + GUID + Type
For example:

id="Shipping_x0020_Cost_69f8ed64-5288-4c68-80d3-49fded8e38ca_CurrencyField" title="Shipping Cost"
    ___________________ ____________________________________ _____________         _____________
	    |				 |			   |			 |
        internal name                   guid 			field type 	    display name

So working with jQuery selectors, we can use this structure to select the controls
e.g.
Get the field where the ID ENDS WITH *type* and the TITLE EQUALS *Display Name*

This will give us the control + the control type
This works quite well because it allows me to work with the display name of the control, so no need to try and figure out the Internal Name SharePoint gives to fields with spaces and special characters. So for example we can build a simple jQuery selector to find the People Picker control

var controlName 	= "Manager";							// My People Picker Control is called "Manager"
var ppDiv 		= $("[id$='ClientPeoplePicker'][title='" + controlName + "']");	// Select the People Picker DIV

It’s important to note that this gives us the outer DIV that contains the various DIVs and SPANs that make up the People Picker. In fact the overall structure of the People Picker is made up of at least 7 different elements.

So how do we Set and Get our values?

Setting values

When setting a People Picker value, the first thing to know is that the People Picker DIV control selected earlier contains an INPUT control. This Input control is a standard HTML textbox and is used as the Editor Input for the People Picker. This is where you type your user name and where the People Picker will display the resolved users. It’s HTML markup looks like this:

<input 
 style="max-width: 366px;" 
 id="Manager_c37cc922-bd42-4b67-8d0b-5d916202acce_$ClientPeoplePicker_EditorInput" 
 class="sp-peoplepicker-editorInput" 
 title="Manager" 
 value="" 
 size="1" 
 type="text" 
 autocorrect="off" 
 autocomplete="off" 
 autocapitalize="off" 
 data-sp-peoplePickerEditor="true" 
 AutoFillContainerId="Manager_c37cc922-bd42-4b67-8d0b-5d916202acce_$ClientPeoplePicker_AutoFillDiv">

Because it is just an Input control, we can manipulate it with jQuery just like anything else

var controlName 	= "Manager";					// My People Picker Control is called "Manager"
var ppDiv 		= $("[id$='ClientPeoplePicker'][title='" + controlName + "']");			// Select the People Picker DIV
var ppEditor 		= ppDiv.find("[title='" + controlName + "']");	// Use the PP DIV to narrow jQuery scope

ppEditor.val("jasonscript\\jason");					// Set the value

This works… partially.
The People Picker will have the text populated, but it won’t be resolved to the actual user record.
On to the next step:

Resolving the User

SharePoint provides us a class: clientpeoplepicker.js

This is located in the _layouts directory so we can easily include it in our page using Scripts on Demand (SP.SOD). From what I’ve seen, it has been present on every page that has a people picker control on it, suggesting that SharePoint itself uses this class to work with the people picker controls

Importantly, this class maintains a dictionary of People Pickers that are on form. The dictionary uses the ID of the containing DIV that we found earlier.
Once we have a handle on our People Picker we have access to all sorts of functions that can help us

var controlName 	= "Manager";					// My People Picker Control is called "Manager"
var ppDiv 		= $("[id$='ClientPeoplePicker'][title='" + controlName + "']");			// Select the People Picker DIV
var ppEditor 		= ppDiv.find("[title='" + controlName + "']");	// Use the PP DIV to narrow jQuery scope
var spPP 		= SPClientPeoplePicker.SPClientPeoplePickerDict[ppDiv[0].id];			// Get the instance of the People Picker from the Dictionary

ppEditor.val("jasonscript\\jason");					// Set the value
spPP.AddUnresolvedUserFromEditor(true);					// Resolve the User

This call to AddUnresolvedUserFromEditor fires off the People Picker validation. It will take any input(s) in the Editor input control and try to resolve them against the SharePoint provider.

How do we retrieve the values? Good question

Retrieving the values

var controlName 	= "Manager";					// My People Picker Control is called "Manager"
var ppDiv 		= $("[id$='ClientPeoplePicker'][title='" + controlName + "']");			// Select the People Picker DIV
var ppEditor 		= ppDiv.find("[title='" + controlName + "']");	// Use the PP DIV to narrow the jQuery scope
var spPP 		= SPClientPeoplePicker.SPClientPeoplePickerDict[ppDiv[0].id];			// Get the instance of the People Picker from the Dictionary

ppEditor.val("jasonscript\\jason");					// Set the value
spPP.AddUnresolvedUserFromEditor(true);					// Resolve the User	if (!spPP.HasInputError) 
{
	var userKeys = spPP.GetAllUserInfo();
	var myUser = userKeys[0];
}

The call to GetAllUserInfo() will return an array of objects, each object representing an entry into the editor
Examining the myUser variable gives us the following information

Type Attribute Value
string AutoFillDisplayText “Jason”
string AutoFillKey “i:0#.w|jasonscript\\jason”
string AutoFillSubDisplayText
string AutoFillTitleText “jason@jasonscript.lab\nActive Directory\njasonscript\\jason”
string Description “jasonscript\\jason”
string DisplayText “Jason”
string DomainText “jasonscript:81”
object EntityData
string EntityData.Department
string EntityData.Email
string EntityData.MobilePhone
string EntityData.SIPAddress
string EntityData.Title
string EntityType “User”
bool IsResolved true
string Key “i:0#.w|jasonscript\\jason”
array MultipleMatches []
string ProviderDisplayName “Active Directory”
string ProviderName “AD”
bool Resolved true

Extra Goodness

The SPClientPeoplePicker object even gives us events!

OnControlValidateClientScript(elemId, userKeys)
OnUserResolvedClientScript(elemId, userKeys)
OnValueChangedClientScript(elemId, userKeys)

Advertisements

20 thoughts on “Javascript and Working with the SharePoint 2013 People Picker

  1. This is great! I’ve been trying to figure out how to resolve a known user from the input text. AddUnresolvedUserFromEditor is exactly what I was missing. What approach did you follow to discover this method? A Google search on this only turns up two (2!) results. This author (http://oddmithril.wordpress.com/2012/10/15/sharepoint-2013-peoplepicker/) describes how to reverse-engineer client-side behavior. I’ll have to checkout WebStorm…

    Thanks again, and congrats for having the first complete walkthrough published on this subject. 😉

    1. Thanks for the great feedback.

      I came across that same oddmithril post when I was working on getting the people picker code to work. It was really just a long time spent on debugging the people picker and trying to understand the javascript. You can download the clientpeoplepicker.js file as well to see what is going on there

  2. It’s more troublesome if you want to add multiple users. But AddUnresolvedUserFromEditor calls a couple other functions that aren’t that bad to reorganize in a loop. I wrote a little jquery plugin wrapper for the whole people picker, here is the “setValues” portion of it:
    note: uses underscorejs

    setValues: function (values) { // values can be a single login or an array of them
    var pp = global.SPClientPeoplePicker.SPClientPeoplePickerDict[$(this).attr(‘id’)+”_TopSpan”];
    _.each(_.union([], values), function (v) {
    var c = global.SPClientPeoplePicker.BuildUnresolvedEntity(v, v);
    pp.AddUnresolvedUser(c, true);
    });
    }
    It only works after first being initialized. If called again, it will just keep adding users (even if it’s the same users).

    Hope that helps somebody.

  3. I’m having an extreme issue trying to get the SPClientPeoplePicker object when trying to default a People Picker on a NewForm.aspx page. Any suggestions? SPClientPeoplePicker.SPClientPeoplePickerDict[ppDiv[0].id] just gives me undefined, and I checked the dictionary itself — null. How would I get a People Picker that SharePoint puts in when it resolves into the People Picker? For help, here is my code:

    ExecuteOrDelayUntilScriptLoaded(function(){
    var ppDiv = $(“[id$=’ClientPeoplePicker’][title=’Owner’]”);
    var ppEditor = ppDiv.find(“[title=’Owner’]”);
    alert(SPClientPeoplePicker.PickerObjectFromSubElement(ppDiv[0]));
    alert(SPClientPeoplePicker.SPClientPeoplePickerDict[0]);

    var spPP = SPClientPeoplePicker.SPClientPeoplePickerDict[ppDiv[0].id];
    ppEditor.val(“domain\\user”);
    spPP.AddUnresolvedUserFromEditor(true);
    }, “clientpeoplepicker.js”);

    All my alerts come back as undefined or null.

    Any help would be appreciated.

  4. Hi Eric,

    I was facing the same issue.Modified the code to make it work.

    ExecuteOrDelayUntilScriptLoaded(function () {
    setTimeout(function () {
    SetUserFieldValue(‘SATP Professional Name’, accountName); }, 2000);
    }, “clientpeoplepicker.js”);

    //Set PeoplePicker Value
    function SetUserFieldValue(fieldName, userName) {
    try{
    //PeoplePicker Object
    var peoplePicker = $(“div[title='” + fieldName + “‘]”);
    //PeoplePicker ID
    var peoplePickerTopId = peoplePicker.attr(‘id’);
    //People PickerEditor
    var peoplePickerEditor = $(“input[title='” + fieldName + “‘]”);
    //Set Value to Editor
    peoplePickerEditor.val(userName);
    //Get Client PeoplePicker Dict
    var peoplePickerObject = SPClientPeoplePicker.SPClientPeoplePickerDict[peoplePickerTopId];
    //Unresolve User From Editor
    peoplePickerObject.AddUnresolvedUserFromEditor(true);
    }catch(e) {

    }
    }//End Set PeoplePicker Value

  5. Thanks for this. Very useful.
    Others please note that using the title in the jQuery selector will only work if the field is not required ( [title='” + controlName + “‘] ). When a field is required, the title tag no longer carries the field’s name but becomes ‘This is a required field’.

  6. Awesome post, Jason! Thanks for figuring this out and sharing it. I’m using this in an Office 365 context, and so far it works great there as well.

  7. hi the above code not working for me.
    I have people picker in form which generated dynamically using below code.

    function initialize_app_PeoplePicker(peoplePickerElementId)
    {
    // Create a schema to store picker properties, and set the properties.
    var schema = {};
    schema[‘PrincipalAccountType’] = ‘User,DL,SecGroup,SPGroup’;
    schema[‘SearchPrincipalSource’] = 15;
    schema[‘ResolvePrincipalSource’] = 15;
    schema[‘AllowMultipleValues’] = true;
    schema[‘MaximumEntitySuggestions’] = 50;
    schema[‘Width’] = ‘190px’;
    //alert(‘In initialize_app_PeoplePicker function\nIdname:’+peoplePickerElementId);
    // Render and initialize the picker.
    // Pass the ID of the DOM element that contains the picker, an array of initial
    // PickerEntity objects to set the picker value, and a schema that defines
    // picker properties.
    SPClientPeoplePicker_InitStandaloneControlWrapper(peoplePickerElementId, null, schema);

    }

    I want to set this people picker from fetching user from list. I used above code but it is giving me error peoplePickerTopId is undefined. please help me with this. I am sending ID_topspan to user function as element id.

    1. Hi Rahul,

      If you’re trying to create a peoplepicker using CSOM, then this article isn’t really going to help. This article was more about working with existing peoplepicker controls. I haven’t tried creating a new peoplepicker to the form before.

      Good luck!

      1. hi jasrus,

        thanks for you code. I am done with functionality. Your code is helpful for me. I have created people picker using csom. and pass that div to above code. littile correction to your code. we do not have to find the inner html element. we can send static value.

    2. Hi Rahul,

      i did it like you and have a div with id=”peoplePickerDiv”. – So following code worked for me.

      var peoplePicker =$(“#peoplePickerDiv”);
      var peoplePickerEditor = $(“#peoplePickerDiv_TopSpan_EditorInput”);

      peoplePickerEditor.val(userName);

      var peoplePickerObject = SPClientPeoplePicker.SPClientPeoplePickerDict[“peoplePickerDiv_TopSpan”];
      peoplePickerObject.AddUnresolvedUserFromEditor(true);

      You can find the ids if you look at the dom after you run InitStandaloneControlWrapper:

      // Enter a name or email address…”

      Good luck, Ronny

  8. Hi Jason! Thanks for the script. Works like a charm for adding people to a people picker, but what if I wanted to remove a name? For example, I have a radio button field that asks if an extra approver is needed. If it’s blank, or no, the approver1 field is hidden. When they select yes, it shows. Now, my client has requested that if somebody checks yes, fills in the field, and then decides otherwise and changes it to no, it clear out the people picker when they select no. Would that be possible?

    Thanks!

    1. Hi Jonas, I haven’t worked with this too much since this article. I did find that there is a spPP.DeleteProcessedUser() method. When the People Picker control is a single user (e.g. not multi-choice) this removes the current selection. There is also spPP.GetAllUserInfo() which seems to return some information about all the currently selected users. Hopefully you can use a combination of these two methods to achieve what you need

  9. Thanks for the Script! I have been able to use it to set the value and get information about the user. Do you have an example on how to use the OnValueChangedClientScript event? I’m trying to add a event if the value of the people picker is changed but haven’t had any luck yet.

  10. Nice article,

    I’ve created a version without jquery:

    var controlName = “Manager”;
    var ppDiv = document.querySelector(“[id$=’ClientPeoplePicker’][title='” + controlName + “‘]”);
    var spPP = SPClientPeoplePicker.SPClientPeoplePickerDict[ppDiv.id];
    var ppEditor = document.getElementById(spPP.EditorElementId);
    ppEditor.value = “domain\\username”;
    spPP.AddUnresolvedUserFromEditor(true);

  11. FYI – your code for Retrieving the value is the same as for setting the value. Can you update with the correct retrieval code?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s