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>