Reputation: 11
I'm trying to create a People Picker field on MSPO's "Create a new project" Page.
I've been using the script in the following post to create People Picker fields within Project Detail Pages. This has worked very well.
People Picker in Microsoft Project Online
Now I'm trying to create a People Picker field on MSPO's "Create a new project" page. The issue I ran into was that all fields on the CreateProject.aspx page exist within an iframe, so the script couldn't find the desired "Project Sponsor" field.
I modified the script to look for the "Project Sponsor" field within a specified iframe ('iframe.pwa-animate-in'), and now it is able to find the field. However, when I test my script in the console, I receive the following error:
Uncaught TypeError: Cannot set properties of undefined
(setting 'OnControlResolvedUserChanged')
"OnControlResolvedUserChanged" is undefined
because "newPeoplePicker" is undefined. "newPeoplePicker" is undefined because
"SPClientPeoplePickerDict" is undefined.
Why is "SPClientPeoplePickerDict" undefined?
<script>
$(document).ready(function () { ExecuteOrDelayUntilScriptLoaded(CustomAction, "sp.js"); });
function CustomAction() {
// Set the following to be an array of fields you would like to change into a people-picker
// Example: var targetFields = ['Custom Field'];
var targetFields = ['Project Sponsor'];
// Safely load JQuery
if (typeof jQuery == 'undefined') {
var s = document.createElement("script");
s.src = '//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js';
if (s.addEventListener) {
s.addEventListener("load", function () { myJQueryCode() }, false);
}
else if (s.readyState) {
s.onreadystatechange = function () { myJQueryCode() };
}
document.getElementsByTagName('head')[0].appendChild(s);
}
else {
console.log('jQuery loaded');
myJQueryCode();
}
var iframe = document.querySelector('iframe.pwa-animate-in');
console.log('iframe found');
var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
console.log(innerDoc.body);
if (innerDoc) {
// Now search within the iframe's document using jQuery
var $innerDoc = $(innerDoc); // Wrap the inner document with jQuery
console.log('inner document wrapped with jQuery');
} else {
console.log('Could not access iframe content document.');
}
function myJQueryCode() {
$(document).ready(function () {
var scriptRoot = _spPageContextInfo.siteAbsoluteUrl + '/_layouts/15/';
$.when(
$.getScript(scriptRoot + "clienttemplates.js"),
$.getScript(scriptRoot + "clientforms.js"),
$.getScript(scriptRoot + "clientpeoplepicker.js"),
$.getScript(scriptRoot + "autofill.js")
)
.done(function () {
window.console && console.log('Scripts loaded');
console.log(scriptRoot + "clienttemplates.js");
console.log(scriptRoot + "clientforms.js");
console.log(scriptRoot + "clientpeoplepicker.js");
console.log(scriptRoot + "autofill.js");
renderPeoplePickers();
})
.fail(function (message) {
window.console && console.error('Loading scripts failed: ' + message);
});
});
}
function renderPeoplePickers() {
console.log('renderPeoplePickers called');
for (var fieldIndex = 0; fieldIndex < targetFields.length; fieldIndex++) {
if (typeof innerDoc == 'undefined') {
$("input[type='text'][title='" + targetFields[fieldIndex] + "']").each(function () {
console.log('Elements found');
this.style.color = "green";
console.log('Color defined');
renderPeoplePicker(this);
window.console && console.log('PeoplePicker rendered: ' + targetFields[fieldIndex]);
});
} else {
$innerDoc.find("input[type='text'][title='" + targetFields[fieldIndex] + "']").each(function () {
console.log('Elements found');
this.style.color = "green";
console.log('Color defined');
renderPeoplePicker(this);
window.console && console.log('PeoplePicker rendered: ' + targetFields[fieldIndex]);
});
}
}
}
function renderPeoplePicker(targetInput) {
console.log(targetInput); // Check what is being logged
var divPeoplePicker = document.createElement('div');
var idPeoplePicker = targetInput.id + '_PeoplePicker';
console.log('idPeoplePicker defined:', idPeoplePicker);
var targetValue = $(targetInput).attr('value');
divPeoplePicker.id = idPeoplePicker;
$(targetInput).parent().append(divPeoplePicker);
initializePeoplePicker(idPeoplePicker);
console.log('this defined:', this);
console.log('SPClientPeoplePicker defined:', SPClientPeoplePicker);
console.log('SPClientPeoplePickerDict defined:', SPClientPeoplePicker.SPClientPeoplePickerDict);
var newPeoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict[idPeoplePicker + '_TopSpan'];
console.log('newPeoplePicker defined:', newPeoplePicker);
$(targetInput).hide();
console.log('hide targetInput');
if (typeof targetValue !== "undefined") {
console.log('targetValue undefined');
var selectedUsers = targetValue.split(";");
for(i=0;i<selectedUsers.length;i++) {
if(selectedUsers[i] && selectedUsers[i] != "") {
newPeoplePicker.AddUnresolvedUser( {
Key: selectedUsers[i],
DisplayText: selectedUsers[i]
}, true);
}
}
}
newPeoplePicker.OnControlResolvedUserChanged = function () {
console.log('newPeoplePicker called');
if (this.TotalUserCount > 0) {
var fieldVal = '';
for(i=0;i<this.GetAllUserInfo().length;i++) {
// We have a resolved user
var resolvedUser = this.GetAllUserInfo()[i];
fieldVal = fieldVal + resolvedUser.DisplayText + ";";
}
// Set the underlying field value
$('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value', fieldVal);
// If value has changed then mark the PDP dirty to enable save
// Thank you to Martin Laukkanen (nearbaseline.com) for this fix!
if ($('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('origvalue') !== $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value')) {
WPDPParts[0].IsDirty = true;
}
}
else {
// We have nothing - so clear out the target field
$('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value', '');
}
}
}
// Render and initialize the client-side People Picker
function initializePeoplePicker(peoplePickerElementId, defaultValue) {
var users;
if ((defaultValue != undefined) && (defaultValue != "")) {
users = new Array(1);
var defaultUser = new Object();
defaultUser.AutoFillDisplayText = defaultValue;
defaultUser.AutoFillKey = defaultValue;
// defaultUser.Description = user.get_email();
defaultUser.DisplayText = defaultValue;
defaultUser.EntityType = "User";
defaultUser.IsResolved = false;
defaultUser.Key = defaultValue;
defaultUser.Resolved = false;
users[0] = defaultUser;
}
else {
users = null;
}
// Create a schema to store picker properties, and set the properties.
var schema = {};
schema['PrincipalAccountType'] = 'User';
// schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';
schema['SearchPrincipalSource'] = 15;
schema['ResolvePrincipalSource'] = 15;
schema['AllowMultipleValues'] = false;
schema['MaximumEntitySuggestions'] = 50;
schema['Width'] = '360px';
// 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
this.SPClientPeoplePicker_InitStandaloneControlWrapper(peoplePickerElementId, users, schema);
}
}
</script>
Upvotes: 1
Views: 47
Reputation: 11
I was able to resolve this issue by adding the following steps to Integent's initial script (https://www.youtube.com/watch?v=cR0W4umH8ZU):
<script>
$(document).ready(function () { ExecuteOrDelayUntilScriptLoaded(CustomAction, "sp.js"); });
function CustomAction() {
// Set the following to be an array of fields you would like to change into a people-picker
// Example: var targetFields = ['Custom Field'];
var targetFields = ['Project Sponsor'];
// Safely load JQuery
if (typeof jQuery == 'undefined') {
var s = document.createElement("script");
s.src = '//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js';
if (s.addEventListener) {
s.addEventListener("load", function () { myJQueryCode() }, false);
}
else if (s.readyState) {
s.onreadystatechange = function () { myJQueryCode() };
}
document.getElementsByTagName('head')[0].appendChild(s);
}
else {
myJQueryCode();
}
// Find the iframe
var iframe = document.querySelector('iframe.pwa-animate-in');
// Search within the iframe's document using jQuery
var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
// Wrap the inner document with jQuery
var $innerDoc = $(innerDoc);
function myJQueryCode() {
$(document).ready(function () {
var scriptRoot = _spPageContextInfo.siteAbsoluteUrl + '/_layouts/15/';
$.when(
$.getScript(scriptRoot + "clienttemplates.js"),
$.getScript(scriptRoot + "clientforms.js"),
$.getScript(scriptRoot + "clientpeoplepicker.js"),
$.getScript(scriptRoot + "autofill.js")
)
.done(function () {
window.console && console.log('Scripts loaded');
renderPeoplePickers();
})
.fail(function (message) {
window.console && console.error('Loading scripts failed: ' + message);
});
});
}
function renderPeoplePickers() {
for (fieldIndex = 0; fieldIndex < targetFields.length; fieldIndex++) {
// Ensure that the script will run regardless of whether an iframe exists
if (typeof innerDoc == 'undefined') {
$("input[type='text'][title='" + targetFields[fieldIndex] + "']").each(function () {
this.style.color = "green";
renderPeoplePicker(this);
window.console && console.log('PeoplePicker rendered: ' + targetFields[fieldIndex]);
});
}
else {
$innerDoc.find("input[type='text'][title='" + targetFields[fieldIndex] + "']").each(function () {
this.style.color = "green";
renderPeoplePicker(this);
window.console && console.log('PeoplePicker rendered: ' + targetFields[fieldIndex]);
});
}
}
}
function renderPeoplePicker(targetInput) {
var divPeoplePicker = document.createElement('div');
var idPeoplePicker = targetInput.id + '_PeoplePicker';
var targetValue = $(targetInput).attr('value');
divPeoplePicker.id = idPeoplePicker;
$(targetInput).parent().append(divPeoplePicker);
initializePeoplePicker(idPeoplePicker);
var newPeoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict[idPeoplePicker + '_TopSpan'];
$(targetInput).hide();
if (typeof targetValue !== "undefined") {
var selectedUsers = targetValue.split(";");
for(i=0;i<selectedUsers.length;i++) {
if(selectedUsers[i] && selectedUsers[i] != "") {
newPeoplePicker.AddUnresolvedUser( {
Key: selectedUsers[i],
DisplayText: selectedUsers[i]
}, true);
}
}
}
newPeoplePicker.OnControlResolvedUserChanged = function () {
if (this.TotalUserCount > 0) {
var fieldVal = '';
for(i=0;i<this.GetAllUserInfo().length;i++) {
// We have a resolved user
var resolvedUser = this.GetAllUserInfo()[i];
fieldVal = fieldVal + resolvedUser.DisplayText + ";";
}
// Set the underlying field value
$('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value', fieldVal);
// If value has changed then mark the PDP dirty to enable save
// Thank you to Martin Laukkanen (nearbaseline.com) for this fix!
if ($('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('origvalue') !== $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value')) {
WPDPParts[0].IsDirty = true;
}
}
else {
// We have nothing - so clear out the target field
$('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value', '');
}
}
}
// Render and initialize the client-side People Picker
function initializePeoplePicker(peoplePickerElementId, defaultValue) {
var users;
if ((defaultValue != undefined) && (defaultValue != "")) {
users = new Array(1);
var defaultUser = new Object();
defaultUser.AutoFillDisplayText = defaultValue;
defaultUser.AutoFillKey = defaultValue;
// defaultUser.Description = user.get_email();
defaultUser.DisplayText = defaultValue;
defaultUser.EntityType = "User";
defaultUser.IsResolved = false;
defaultUser.Key = defaultValue;
defaultUser.Resolved = false;
users[0] = defaultUser;
}
else {
users = null;
}
// Create a schema to store picker properties, and set the properties
var schema = {};
schema['PrincipalAccountType'] = 'User';
// schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';
schema['SearchPrincipalSource'] = 15;
schema['ResolvePrincipalSource'] = 15;
schema['AllowMultipleValues'] = false;
schema['MaximumEntitySuggestions'] = 50;
schema['Width'] = '360px';
// 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
this.SPClientPeoplePicker_InitStandaloneControlWrapper(peoplePickerElementId, users, schema);
}
}
// Wait for the iframe to load
window.onload = function(){
CustomAction();
};
</script>
Upvotes: 0