I am trying to implement a solution in SharePoint Online by customizing the NewForm.aspx page of a out of the box Calendar List using JavaScript with the following requirements:
- When page loads, a people picker field gets automatically populated with the current logged in user (and automatically resolved)
- If a the user changes the value of the people picker, I want to be able to detect the value change event so that I can apply some custom logic
For the first requirement, I was able to populate the people picker field but not automatically resolve it. For the second requirement, I was not able to detect the change on the poeple picker’s value.
In the end you can find the code I am using and it contains several approaches on second requirement that I was still not able to put any of them to work.
The problem seems to be accessing the people picker object itself using the following code:
var peoplePickerDiv = jQuery("div[title='People Picker']"); var peoplePickerDivId = peoplePickerDiv.attr('id'); var peoplePickerObject = SPClientPeoplePicker.SPClientPeoplePickerDict[peoplePickerDivId];
In runtime, the peoplePickerObject is always null.
In the research I made on the Internet, any solution to address both requirements used the above code, i.e., getting a SPClientPeoplePicker object by accessing SPClientPeoplePickerDict supplying the people picker’s Id. I confirmed that the id I am supplying is correct.
NOTE: I was able to successfully use the same approach against on-prem SharePoint 2013 but not with SharePoint Online. Not sure if HTML of the people picker changed or there is a different behavior of the JavaScript API to get SPClientPeoplePicker objects in SharePoint Online in comparison with on-prem SharePoint 2013.
Did someone found the same problem and was able to solve it?
Code I am using:
<script type="text/javascript" src="/_layouts/15/clientforms.js"></script> <script type="text/javascript" src="/_layouts/15/clientpeoplepicker.js"></script> <script type="text/javascript" src="/_layouts/15/autofill.js"></script> <script type="text/javascript"> var loginName; jQuery(document).ready(function () { //alert("page loaded"); SetPeoplePickerWithCurrentUser(); SetCurrentUserAvailableDays(); jQuery(".ms-inputuserfield").bind('input propertychange', function() { alert("Onchange event" ); }) ExecuteOrDelayUntilScriptLoaded(function () { setTimeout(function () { attachPeoplePickerChange(); }, 2000); }, 'clientpeoplepicker.js'); /*jQuery(".ms-inputuserfield textarea").change(function() { alert( "Handler for .change() called." ); }); jQuery(".ms-input").change(function() { alert( "Handler for input .change() called." ); });*/ //attachPeoplePickerChange(); }); /*End document ready*/ function SetPeoplePickerWithCurrentUser() { var userid = _spPageContextInfo.userId; //alert("userid: " + userid); var endpointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")"; var requestHeaders = { "accept" : "application/json;odata=verbose" }; jQuery.ajax({ type: "GET", url: endpointUrl, contentType: "application/json; charset=utf-8", dataType: "json" }) .done(function (data) { loginName = data.Title; //alert("loginName: " + loginName); //SetUserFieldValue("Colaborador",loginName); window.setTimeout(SetPeoplePicker, 500); //SetUserFieldValue("People Picker",loginName); }) .fail(function (jqXHR, textStatus, errorThrown) { alert("Error: " + errorThrown); console.log(jqXHR.status + " : " + textStatus + " - " + errorThrown); }) .always(function () { }); } function SetPeoplePicker() { SetUserFieldValue("People Picker", loginName); } function SetUserFieldValue(fieldName, userName) { var peoplePickerDiv = jQuery("div[title='" + fieldName + "']"); var peoplePickerDivId = peoplePickerDiv.attr('id'); //var peoplePickerEditorInput = jQuery("input[title='" + fieldName + "']"); //var peoplePickerEditorInput = jQuery("textarea[title='" + fieldName + "']"); var peoplePickerEditorInput = peoplePickerDiv.find("[title='" + fieldName + "']"); //alert(userName); //peoplePickerEditorInput.val(userName); jQuery("div[title='People Picker']").text(userName); //Find the Specific People picker field "Colaborador" and set its value /*jQuery().SPServices.SPFindPeoplePicker({ peoplePickerDisplayName: "Colaborador", valueToSet: user, checkNames: true });*/ //var peoplePickerEditorObject = SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan; //var peoplePickerEditorObject = SPClientPeoplePicker.SPClientPeoplePickerDict[peoplePickerDivId]; //var peoplePickerEditorObject = SPClientPeoplePicker.SPClientPeoplePickerDict["ctl00_ctl40_g_a543006a_dd2e_46e0_93c8_deeb4d72af44_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_UserField_downlevelTextBox"]; //peoplePickerEditorObject.AddUnresolvedUserFromEditor(true); //_PeoplePickerEditor.attr("disabled", "disabled"); } function SetCurrentUserAvailableDays() { var userid = _spPageContextInfo.userId; //alert("userid: " + userid); var endpointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Dias Férias 2016')/items?$ filter=IniciaisId eq " + userid; var requestHeaders = { "accept" : "application/json;odata=verbose" }; jQuery.ajax({ type: "GET", url: endpointUrl, contentType: "application/json; charset=utf-8", dataType: "json" }) .done(function (data) { var availableDays = data.value[0].Dias_x0020_dispon_x00ed_veis; jQuery("input[title='Dias úteis']").val(availableDays); }) .fail(function (jqXHR, textStatus, errorThrown) { alert("Error: " + errorThrown); console.log(jqXHR.status + " : " + textStatus + " - " + errorThrown); }) .always(function () { }); } function attachPeoplePickerChange() { //container needs to be an dom element containing the peoplepicker var peoplePickerDiv = jQuery("div[title='People Picker']"); var peoplePickerDivId = peoplePickerDiv.attr('id'); //helper function to ensure all elements are already created var addOnChanged = function (ctx) { //alert("addOnChanged"); //is everything ready we need? if (SPClientPeoplePicker && SPClientPeoplePicker.SPClientPeoplePickerDict && SPClientPeoplePicker.SPClientPeoplePickerDict[peoplePickerDivId]) { //get picker instance (which has a lot of useful properties btw) alert("addOnChanged"); var picker = SPClientPeoplePicker.SPClientPeoplePickerDict[peoplePickerDivId]; //save old event (needs to stay in its context due to internal calls picker.oldChanged = picker.OnControlResolvedUserChanged; picker.OnControlResolvedUserChanged = function () { //do your code here console.log('OnControlResolvedUserChanged'); //get current selected users console.log(picker.GetAllUserInfo()); //let old event do its magic picker.oldChanged(); }; } else { //not everything was ready - wait a 10th of a sec setTimeout(function () { addOnChanged(ctx); }, 100); } }; addOnChanged(); } </script>
I compared html in SharePoint 2013 onprem with SharePoint Online and they in fact different:
OnPrem:
<div title="Utilizador" class="sp-peoplepicker-topLevel sp-peoplepicker-topLevelFocus" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker" SPClientPeoplePicker="true"><input name="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_HiddenInput" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_HiddenInput" type="hidden" value='[{"Key":"i:0#.w|dev\sp_admin","Description":"DEV\sp_admin","DisplayText":"SharePoint Admin","EntityType":"User","ProviderDisplayName":"Active Directory","ProviderName":"AD","IsResolved":true,"EntityData":{"Title":"","MobilePhone":"","SIPAddress":"","Department":"","Email":""},"MultipleMatches":[],"Resolved":true}]'><div class="sp-peoplepicker-autoFillContainer" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_AutoFillDiv" style="left: -1px; top: 26px;" InputElementId="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_EditorInput"></div><span class="sp-peoplepicker-initialHelpText ms-helperText" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_InitialHelpText" style="display: none;">Introduza um nome ou endereço de correio eletrónico...</span><img class="sp-peoplepicker-waitImg" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_WaitImage" style="left: 376px; top: 4px; display: none;" alt="Esta animação indica que a operação está em curso. Clique para remover esta imagem animada." src="/_layouts/15/images/gears_anv4.gif?rev=23"><span class="sp-peoplepicker-resolveList" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_ResolvedList"><span class="sp-peoplepicker-userSpan" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_i:0#.w|dev\sp_admin_ProcessedUser1" sid="i:0#.w|dev\sp_admin" resolveduser="true" data-sp-peoplepickerprocesseduser="true"><span class="sp-peoplepicker-userPresence" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_i:0#.w|dev\sp_admin_ProcessedUser1_PresenceContainer"></span><span title="SharePoint Admin" class="ms-entity-resolved" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_i:0#.w|dev\sp_admin_ProcessedUser1_UserDisplay" style="max-width: 331px;">SharePoint Admin</span><a title="Remover pessoa ou grupo SharePoint Admin" class="sp-peoplepicker-delImage" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_i:0#.w|dev\sp_admin_ProcessedUser1_DeleteUserLink" onkeydown="SPClientPeoplePickerProcessedUser.HandleDeleteProcessedUserKey(event); return true;" onclick="SPClientPeoplePickerProcessedUser.DeleteProcessedUser(this.parentNode); return false;" href="#">x</a></span></span><input title="Utilizador" disabled="disabled" class="sp-peoplepicker-editorInput" id="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_EditorInput" style="max-width: 366px;" type="text" size="1" value="" autocorrect="off" autocomplete="off" autocapitalize="off" data-sp-peoplePickerEditor="true" AutoFillContainerId="aps_user_13fce4eb-973e-44b9-8cba-ff3d6cddd687_$ ClientPeoplePicker_AutoFillDiv"></div>
SharePoint Online:
<textarea name="ctl00$ ctl40$ g_a543006a_dd2e_46e0_93c8_deeb4d72af44$ ctl00$ ctl05$ ctl06$ ctl00$ ctl00$ ctl04$ ctl00$ ctl00$ UserField$ downlevelTextBox" title="People Picker" class="ms-inputuserfield ms-inputBox" id="ctl00_ctl40_g_a543006a_dd2e_46e0_93c8_deeb4d72af44_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_UserField_downlevelTextBox" style="width: 100%; display: none; ;" onkeydown="return onKeyDownRw('ctl00_ctl40_g_a543006a_dd2e_46e0_93c8_deeb4d72af44_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_UserField', 3, true, event);" onkeyup="return onKeyUpRw('ctl00_ctl40_g_a543006a_dd2e_46e0_93c8_deeb4d72af44_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_UserField');" onfocus="StoreOldValue('ctl00_ctl40_g_a543006a_dd2e_46e0_93c8_deeb4d72af44_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_UserField'); saveOldEntities('ctl00_ctl40_g_a543006a_dd2e_46e0_93c8_deeb4d72af44_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_UserField'); Sys.UI.DomElement.addCssClass(this, 'ms-inputBoxActive');" onblur="if(typeof(ExternalCustomControlCallback)=='function'){ if(ShouldCallCustomCallBack('ctl00_ctl40_g_a543006a_dd2e_46e0_93c8_deeb4d72af44_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_UserField',event)){if(!ValidatePickerControl('ctl00_ctl40_g_a543006a_dd2e_46e0_93c8_deeb4d72af44_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_UserField')){ShowValidationError();return false;}else {ExternalCustomControlCallback('ctl00_ctl40_g_a543006a_dd2e_46e0_93c8_deeb4d72af44_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_UserField');}}} Sys.UI.DomElement.removeCssClass(this, 'ms-inputBoxActive');" onchange="updateControlValue('ctl00_ctl40_g_a543006a_dd2e_46e0_93c8_deeb4d72af44_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_UserField');" rows="1" cols="20" autopostback="0" renderascontenteditablediv="true"></textarea>