Working with SharePoint People Pickers with jQuery: A New Function Called findPeoplePicker

[notice]2012-09-07 – Note that I’ve added a more robust version of this function into SPServices v0.7.2, which at this writing is in beta but will be released soon. See the docs for SPFindPeoplePicker.[/notice]

I was working with several People Pickers in a form for a client project last week where I needed to set or get their values at various times in the page lifecycle. These things are pesky little compound controls, I often need to find them in the page, and I get tired of writing new script every time I want to do it. I’ve posted in the past about how to get the value with JavaScript, set the value with JavaScript, set one with jQuery, and more. It seemed high time to just write a little function to give me everything I needed in one go.

Here’s what I came up with:

[important]UPDATE 2012-04-24 – I made a dumb mistake by using :contains() in the selector for thisRow, which occasionally returned unwanted results. I fixed it with the .filter() function below.[/important]

// Find a People Picker in the page
// Returns references to:
//   row - The TR which contains the People Picker (useful if you'd like to hide it at some point)
//   contents - The element which contains the current value
//   currentValue - The current value if it is set
//   checkNames - The Check Names image (in case you'd like to click it at some point)
$.fn.findPeoplePicker = function(options) {

  var opt = $.extend({}, {
    peoplePickerDisplayName: "",	// The displayName of the People Picker on the form
    valueToSet: "",			// The value to set the People Picker to. Should be a string containing each username or groupname separated by semi-colons.
    checkNames: true			// If set to true, the Check Names image will be clicked to resolve the names
  }, options);

  // Find the row containing the People Picker
  var thisRow = $("nobr").filter(function() {
    return $(this).text() == opt.peoplePickerDisplayName;
  }).closest("tr");
  var thisContents = thisRow.find("div[Title='People Picker']");
  var thisCheckNames = thisRow.find("img[Title='Check Names']:first");
  if(opt.valueToSet.length > 0) thisContents.html(opt.valueToSet);
  if(opt.checkNames) thisCheckNames.click();
  var thisCurrentValue = thisContents.text();

  return {row: thisRow, contents: thisContents, currentValue: thisCurrentValue, checkNames: thisCheckNames};
}

This function doesn’t just find the People Picker in the form, it also allows you to set it and, if you choose, click the Check Names image automagically. It also returns a JSON object which contains references to the important elements which make up the People Picker so that you can work with them later. Unfortunately, the only thing I can key on to find the darn things in the page is the <nobr> element which contains the DisplayName of the column. There’s just not anything else in the People Pickers which distingishes them from each other other than the standard comment, like so:

<!--  FieldName="Site Contact"
			 FieldInternalName="Site_x0020_Contact"
			 FieldType="SPFieldUser"
		   -->

Uising that comment has always seemed even less reliable to me than the DisplayName, even though I select for it in SPServices in several places. (If I’m missing something, please let me know.)

Here are a few example calls:

// Set the Site Contact to the current user
siteContactPeoplePicker = $().findPeoplePicker({
  peoplePickerDisplayName: "Site Contact",
  valueToSet: $().SPServices.SPGetCurrentUser()
});
// Find the Stakeholders People Picker in the form for later us
stakeholdersPeoplePicker = $().findPeoplePicker({
  peoplePickerDisplayName: "Stakeholders",
  checkNames: false
});

In the first call, I’m setting the Site Contact to the current user and resolving the name. In the second call, I’m getting references to the important objects for the StakeHolders People Picker so that I can set the value variably later, like so:

// Set the Stakeholders column value
stakeholdersPeoplePicker.contents.html(stakeholderNames);
stakeholdersPeoplePicker.checkNames.click();

I think some variation of this would be helpful to add to SPServices, even though it has nothing to do with the Web Services. Would you use it? What else would you want it to do?

Similar Posts

62 Comments

  1. Have had no luck getting this to work in 2013 SharePoint Online InfoPath forms with multiple people pickers.

    1. I’m not at all surprised. InfoPath forms are a whole other beast. All of the SPServices value-added functions are meant for the regular list forms.

      M.

      1. Any tips on how to work with InfoPath forms? I’ve found that firing the onFocus event resolves and populates the hidden textbox behind the div and all is well. This only works for the first people picker on the page though.

  2. Not that this belongs in here, but InfoPath will show peoplepicker by default if the underlying SharePoint field is a “Person” type. You can pre populate it on load event with the current user by calling the getProfileByUserName() of the SharePoint profile web service.

  3. Hi Marc,

    First of all I would like to thank you for providing the amazing SPServices framework and It definitely saves lot of my time.

    I was trying to use SPFindPeoplePicker in SP2013 but it was not working might because the rendering format of People Picker as changed. Finally ended up with the below snippet

    function SetAndResolvePeoplePicker(fieldName, userAccountName) {

    var controlName = fieldName;

    var peoplePickerDiv = $(“[id$=’ClientPeoplePicker’][title='” + controlName + “‘]”);

    var peoplePickerEditor = peoplePickerDiv.find(“[title='” + controlName + “‘]”);

    var spPeoplePicker = SPClientPeoplePicker.SPClientPeoplePickerDict[peoplePickerDiv[0].id];

    peoplePickerEditor.val(userAccountName);

    spPeoplePicker.AddUnresolvedUserFromEditor(true);

    peoplePickerDiv[0].disabled = true;

    }

    i have also posted this snippet on my post
    http://www.sharepointcolumn.com/sp2013-setting-people-picker-value-in-newform-aspx/

    Please let me know if there is better way of doing this.

  4. Hi Mark,

    I am working in SP 2013 for people picker. I have a requirement to make people picker readonly in edit form.
    I am able to make the PP disable using the below code. but i can still click on the ‘x’ and delete the name of the user from the control.

    var controlName = “Requestor”;
    var peoplePickerDiv = $(“[id$=’ClientPeoplePicker’][title='” + controlName + “‘]”);
    peoplePickerDiv[0].disabled = true;

    Please help me to resolve this issue.

    Regards,
    Yogendra

  5. Hi Marc,

    Your articles are also been helping for me.

    I have an issue with people pikcer. I am working in SharePoint 2013 and trying to hide people picker on editform.aspx using javascript.

    the hiding works fine if there is no value in the people picker but it gives me an “Invalid Argument” error (clientpeoplepicker.js) if there is any value in it.

    below is my code.

    var control = GetControl(“Approver”);
    control.parentNode.parentNode.style.display=”none”;

    function GetControl(FieldName)
    {
    var arr = document.getElementsByTagName(“!”);
    for(var i=0;i 0){
    return arr[i];
    }
    }
    }

    Kindly help me to resolve this issue.

    Regards,
    Yogendra

    1. Rlyaz:

      There’s nothing in the current SPServices function to do this, but you could add your own. If you think this would be a good addition to the SPFindPeoplePicker functionality, please request it in the Codeplex Issue Tracker.

      M.

  6. This was such an overbloated example, and using “.find()”, “.extend()”, and “.filter()” on any of this is ridiculous when you can use the jQuery selectors directly on the object, itself. In the words of David Thoreau: “Simplify, simplify” !!!!!!!!!!!!!!!! The same could be achieved with FAR fewer lines of code in SP 2010:

    // Default the Requestor’s Name
    var welcomeText = $(‘[id*=”zz8_Menu”]’).text(); // this is zz7_Menu in SP 2007
    var user = welcomeText.split(‘Welcome ‘)[1];
    var counter=0;
    $(‘div[title=”People Picker”]’).each(function() {
    //alert(counter);
    if (counter == 1) { // this is because I wanted to default the 2nd people picker on the page
    $(this).html(user); // <— this is the magic, using .html() on the div
    }
    counter++;
    $('a[title="Check Names"]').click(); // <– this will click the Check Names to resolve your user
    });

    1. vapcguy:

      It doesn’t seem to me that your example is much better. Keep in mind that I write my examples to work in the general case, whereas your code will only work in your specific case. For instance, the second People Picker in the page, the welcome text id being zz8_Menu, etc.

      M.

Leave a Reply

Your email address will not be published. Required fields are marked *

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