In Focus

SharePoint 2016/2013 - Exploring Client Side People Picker Control

In this demo, I will be discussing the implementation details of the Client Side People Picker Control in Production Scenarios.

People Picker control holds a well-known reputation in SharePoint Environment as being a reliable source of selecting SharePoint Users & Groups.

Since the current & recommended SharePoint Development strategies are pointing towards the Client Side Development Techniques, discussing Client Side counterpart of People Picker Control (Libraries) becomes much more useful.

In this demo, I will be discussing the implementation details of the Client Side People Picker Control in Production Scenarios.

I developed this POC as a tool which is an addition to my toolset and often proves helpful to deal with investigating User Properties by querying User Profile Service & and basic property set associated with this control.

To start with this demo, I have added some of the UI elements as described below.

  • User Selection - This section will be having Client Side People Picker Control implementation which further allows user selection.
  • User ID - This section will display User ID of the selected User, which is a crucial piece of information while working out test scenarios.
  • People Picker Properties - This section will display the User Properties that can be retrieved from the People Picker Objects.
  • User Profile Properties - This section will display the User Properties that can be retrieved from the User Profile Service based on the selected User Account.

    1

In the next few screenshots, we can see the HTML laid down to implement this simple UI.

Notice the Div with ID ppOwner”.  This will be the placeholder for the People Picker Control HTML replaced later on.

2

Div with ID UserID will hold the User ID information.

3

Div with ID resolvedUser will hold the People Picker Properties.

4

Div with ID userProfileProperties will hold the User Profile Properties for the selected user.

5

Let’s look at the code file that is implementing the logic behind this tool as described in below steps:

Step 1

Include all the JS files into your code as shown in the screenshot below.

Since these files are inter-referenced, the sequence here is critical. Make sure to include the files in the same sequence.

6

Step 2

initializePeoplePicker is a generic function that defines the schema settings for the Client Side People Picker control which defines the behavior of this control.

Step 3

registerPPOOnChangeEvent is the function used to register events for People Picker Control.

78

Step 4

This step shows the registration of OnControlResolvedUserChanged Event that will be executed every time a valid user is selected using the People Picker control.

Step 5

Once this event is fired, it will make a call to Execute Function.

9

Step 6

Inside the Execute function, we have to first create an object to People Picker Control. It is important to note the convention to write the code:

“this.SPClientPeoplePicker.SPClientPeoplePickerDict.” + <Enter ID of the people picker Div Element> + “_TopSpan”;

Based on this convention, we have an object created as follows:

var peoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict.ppOwner_TopSpan;

Step 7

Once the object has been initialized, we can call GetAllUserInfo function that will return a dictionary of User Properties in the form of Key & Values for each user selected in the People Picket (if multi-selection is enabled).

Step 8

Get each of the users from the dictionary and pass it to another function getUserDetails that will use this to further query User Profile Properties.

Step 9

Retrieving the User ID out of Properties dictionary and showing it in the User ID section.

10

Step 10

Call User Profile REST End Point by passing username with a domain ([domainName]\[userName]) from the Step 8.

Step 11

If the REST Call is successful, pass the user properties collection to the “renderUserDetails” function to display all the properties in User Profile Properties Section.

Step 12

If the REST Call is failed, we can handle the exceptions in this callback function.

11

Step 13

“getUserId” function takes the username with domain ([domainName]\[userName]) as input parameter. This function will return a promise that we are consuming in Step 9.

12

Step 14

“renderUserDetails” function takes user properties dictionary as input from Step 11. Loop it through each of the dictionary entry and render the data in User Profile Properties Section.

13

And, this is all for the code.

In order to test the implementation, let's go back to the People Picker page and select the required User you would like to look for.

14

On selection and if this user is valid (resolved), we will able to see the User Properties as shown below.

151617

Code Snippet
  1. <!DOCTYPE html>  
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml">  
  3. <head>  
  4.     <meta charset="utf-8" />  
  5.     <title></title>  
  6.     <link rel="stylesheet" href="/sites/04773/devpocs/SiteAssets/Client-Side-People-Picker/jquery-ui.css">  
  7.     <link rel="stylesheet" href="/sites/04773/firewallworkflow/SiteAssets/FW-CISM-Assets/bootstrap.min.css">  
  8.     <link rel="stylesheet" href="/sites/04773/devpocs/SiteAssets/Client-Side-People-Picker/CustomCSS.css">  
  9.     <script src="/sites/04773/devpocs/SiteAssets/Client-Side-People-Picker/jquery-1.12.4.js"></script>  
  10.     <script type="text/javascript" src="_layouts/15/sp.runtime.js"></script>  
  11.     <script type="text/javascript" src="_layouts/15/sp.js"></script>  
  12.     <script type="text/javascript" src="_layouts/15/clientpeoplepicker.js"></script>  
  13.     <script type="text/javascript" src="_layouts/15/clienttemplates.js"></script>  
  14.     <script type="text/javascript" src="_layouts/15/clientforms.js"></script>  
  15.     <script type="text/javascript" src="_layouts/15/autofill.js"></script>  
  16.     <script type="text/javascript" src="_layouts/15/sp.core.js"></script>  
  17.     <script type="text/javascript" src="_layouts/15/sp.RequestExecutor.js"></script>  
  18.     <script type="text/javascript">  
  19.         $(document).ready(function () {  
  20.             initializePeoplePicker('ppOwner'nullnull'480'false);  
  21.             registerPPOnChangeEvent($("#ppOwner"));  
  22.         });  
  23.         function registerPPOnChangeEvent(ppElement) {  
  24.             var ppId = ppElement.attr('id')+"_TopSpan";  
  25.             var addOnChanged = function (ctx) {  
  26.                 if (SPClientPeoplePicker && SPClientPeoplePicker.SPClientPeoplePickerDict && SPClientPeoplePicker.SPClientPeoplePickerDict[ppId]) {  
  27.                     var picker = SPClientPeoplePicker.SPClientPeoplePickerDict[ppId];  
  28.                     picker.oldChanged = picker.OnControlResolvedUserChanged;  
  29.                     picker.OnControlResolvedUserChanged = function () {  
  30.                         if (picker.TotalUserCount == 0) {  
  31.                             $('#resolvedUsers').html("");  
  32.                             $('#userKeys').html("");  
  33.                             $("#userProfileProperties").html("");  
  34.                             $("#UserID").html("");  
  35.                         }  
  36.                         else {  
  37.                             // If user name is resolved  
  38.                             setTimeout(function ()  
  39.                             {  
  40.                                 Execute();  
  41.                             }, 100);  
  42.                         }  
  43.                         picker.oldChanged();  
  44.                     };  
  45.                 } else {  
  46.                     setTimeout(function () { addOnChanged(ctx); }, 100);  
  47.                 }  
  48.             };  
  49.             addOnChanged();  
  50.         }  
  51.         function Execute() {  
  52.             // Get the people picker object from the page.  
  53.             var peoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict.ppOwner_TopSpan;  
  54.             // Get information about all users.  
  55.             var users = peoplePicker.GetAllUserInfo();  
  56.             var userInfo = '';  
  57.             for (var i = 0; i < users.length; i++) {  
  58.                 var user = users[i];  
  59.                 for (var userProperty in user) {  
  60.                     userInfo += userProperty + ':  ' + user[userProperty] + '<br>';  
  61.                     if (userProperty == "Description") {  
  62.                         getUserDetails(user[userProperty]);  
  63.                     }  
  64.                     if (userProperty == "Key") {  
  65.                         getUserId(user[userProperty]).done(function (user) {  
  66.                             $("#UserID").html("<h2>User ID : " + user.d.Id + "</h2>");  
  67.                         });  
  68.                     }  
  69.                 }  
  70.             }  
  71.             $('#resolvedUsers').html(userInfo);  
  72.             // Get user keys.  
  73.             var keys = peoplePicker.GetAllUserKeys();  
  74.         }  
  75.         function getUserId(userName) {  
  76.             var siteUrl = _spPageContextInfo.siteAbsoluteUrl;  
  77.             var call = $.ajax({  
  78.                 url: siteUrl + "/_api/web/siteusers(@v)?@v='" + encodeURIComponent(userName) + "'",  
  79.                 method: "GET",  
  80.                 async: false,  
  81.                 headers: { "Accept""application/json; odata=verbose" },  
  82.             });  
  83.             return call;  
  84.         }  
  85.         function getUserDetails(userDomainName) {  
  86.             var requestUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/sp.userprofiles.peoplemanager/getpropertiesfor(@v)?@v='" + userDomainName + "'";  
  87.             var requestDetails = jQuery.ajax({  
  88.                 url: requestUrl,  
  89.                 type: "GET",  
  90.                 dataType: "json",  
  91.                 headers: {  
  92.                     Accept: "application/json;odata=verbose"  
  93.                 }  
  94.             });  
  95.             requestDetails.done(function (data, textStatus, jqXHR) {  
  96.                 if (data.d.UserProfileProperties.results.length > 0) {  
  97.                     renderUserDetails(data.d.UserProfileProperties.results);  
  98.                 }  
  99.             });  
  100.             requestDetails.fail(function (jqXHR, textStatus, errorThrown) {  
  101.                 var response = JSON.parse(jqXHR.responseText);  
  102.                 var message = response ? response.error.message.value : textStatus;  
  103.                 releaseScreen("Call failed. Error: " + message);  
  104.             });  
  105.         }  
  106.         function renderUserDetails(userPropertiesCollection)  
  107.         {  
  108.             var userInfo = '';  
  109.             jQuery.each(userPropertiesCollection, function (index, value) {  
  110.                 userInfo += "<span>"+value.Key+"</span>" + ':  ' + value.Value + '<br>';  
  111.             });  
  112.             $("#userProfileProperties").html(userInfo);  
  113.         }  
  114.         function initializePeoplePicker(peoplePickerElementId, displayName, userName, width, AllowMultipleValues) {  
  115.             var schema = {};  
  116.             schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';  
  117.             schema['SearchPrincipalSource'] = 15;  
  118.             schema['ResolvePrincipalSource'] = 15;  
  119.             schema['AllowMultipleValues'] = AllowMultipleValues;  
  120.             schema['MaximumEntitySuggestions'] = 50;  
  121.             schema['Width'] = width + 'px';  
  122.             schema['margin-left'] = '5px';  
  123.             schema['height'] = '50px';  
  124.             var users = null;  
  125.             if (displayName != null) {  
  126.                 users = new Array(1);  
  127.                 var user = new Object();  
  128.                 user.AutoFillDisplayText = displayName;  
  129.                 user.AutoFillKey = userName;  
  130.                 user.AutoFillSubDisplayText = "";  
  131.                 user.DisplayText = displayName;  
  132.                 user.EntityType = "User";  
  133.                 user.IsResolved = true;  
  134.                 user.Key = userName;  
  135.                 user.ProviderDisplayName = "Tenant";  
  136.                 user.ProviderName = "Tenant";  
  137.                 user.Resolved = true;  
  138.                 users[0] = user;  
  139.             }  
  140.             this.SPClientPeoplePicker_InitStandaloneControlWrapper(peoplePickerElementId, users, schema);  
  141.         }  
  142.     </script>  
  143. </head>  
  144. <body>  
  145.     <div class="container">  
  146.         <table class="clspagetable" cellpadding="0" cellspacing="0" border="1">  
  147.             <caption>  
  148.                 <span> People Picker </span>  
  149.             </caption>  
  150.             <tbody>  
  151.                 <tr>  
  152.                     <td>  
  153.                         <table class="clscontenttable">  
  154.                             <caption>  
  155.                                 <span>User Selection</span>  
  156.                             </caption>  
  157.                             <tbody>  
  158.                                 <tr>  
  159.                                     <td class="tdlable">  
  160.                                         <label>User</label>  
  161.                                     </td>  
  162.                                     <td>  
  163.                                         <div class="inputControls" id="ppOwner" style="margin-top:0px;"></div>  
  164.                                     </td>  
  165.                                 </tr>  
  166.                             </tbody>  
  167.                         </table>  
  168.                     </td>  
  169.                 </tr>  
  170.                 <tr>  
  171.                     <td>  
  172.                         <table class="clscontenttable">  
  173.                             <caption>  
  174.                                 <span>User ID</span>  
  175.                             </caption>  
  176.                             <tbody>  
  177.                                 <tr>  
  178.                                     <td class="tdlable">  
  179.                                         <div id="UserID">  
  180.                                         </div>  
  181.                                     </td>  
  182.                                 </tr>  
  183.                             </tbody>  
  184.                         </table>  
  185.                     </td>  
  186.                 </tr>  
  187.                 <tr>  
  188.                     <td>  
  189.                         <table class="clscontenttable">  
  190.                             <caption>  
  191.                                 <span>People Picker Properties</span>  
  192.                             </caption>  
  193.                             <tbody>  
  194.                                 <tr>  
  195.                                     <td class="tdlable">  
  196.                                         <div id="resolvedUsers">  
  197.                                         </div>  
  198.                                     </td>  
  199.                                 </tr>  
  200.                             </tbody>  
  201.                         </table>  
  202.                     </td>  
  203.                 </tr>  
  204.                 <tr>  
  205.                     <td>  
  206.                         <table class="clscontenttable">  
  207.                             <caption>  
  208.                                 <span>User Profile Properties</span>  
  209.                             </caption>  
  210.                             <tbody>  
  211.                                 <tr>  
  212.                                     <td class="tdlable">  
  213.                                         <div id="userProfileProperties">  
  214.                                         </div>  
  215.                                     </td>  
  216.                                 </tr>  
  217.                             </tbody>  
  218.                         </table>  
  219.                     </td>  
  220.                 </tr>  
  221.             </tbody>  
  222.         </table>  
  223.     </div>  
  224. </body>  
  225. </html>  

That is all for this demo.

Hope you will find it helpful.