2

I'm in a SharePoint 2013 on-prem farm. I have a people picker field called Managers that I want to populate based on users in another people picker field. Once the user clicks Save on the New Form, it reads the Users people picker and populates the Managers people picker. I have it all working except that the Managers field doesn't resolve in time before the save action redirects. I see the Manager being populated just before the page redirects, but when I inspect the new item, the Manager field is not populated. If I have an error on the new form (ex: missing a required field), it will correctly show the resolved manager in the field and hitting submit will then keep the manager field. I think the issue has to do with the fact that I have to query the manager asynchronously in the PreSaveAction, but I'm not sure how to get around that.

EDIT: So as soon as I hit Submit I realized I left out some crucial code below. I updated my code so that it properly reflects what I am working with.

function PreSaveAction() {

  SP.SOD.loadMultiple(['sp.core.js', 'sp.runtime.js', 'sp.js', 
  'autofill.js', 'clientpeoplepicker.js', 'clientforms.js', 'clienttemplates.js'], 
  function() {
     PopulateManager();
  });

  return true;
}

function PopulateManager() {
  SP.SOD.executeFunc('userprofile', 'SP.UserProfiles.PeopleManager', function() {
  var clientContext = new SP.ClientContext.get_current();
  var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);

  nominees = $(".sp-peoplepicker-userSpan[id*='Nomination_x0028_s_x0029']");

  $.each(nominees, function(index,value){
    var username = $(value).attr("sid").split("|")[1];
    var profilePropertyNames = ["Manager"];
    var userProfilePropertiesForUser = new SP.UserProfiles.UserProfilePropertiesForUser(clientContext, username, profilePropertyNames);
    var userProfileProperties = peopleManager.getUserProfilePropertiesFor(userProfilePropertiesForUser);

    clientContext.load(userProfilePropertiesForUser);
    clientContext.executeQueryAsync(
      function(){ 
        GetManagerSuccess(userProfileProperties);
      }, AsyncFail);
    });
});
}


function GetManagerSuccess(userProfileProperties) {
  //I've tried email and i:0#.w|domain\username as well
  var manager = userProfileProperties[0]; //domain\username; 
  var peoplePicker = 
  SPClientPeoplePicker.SPClientPeoplePickerDict["Managers_" 
    + 
    WPQ2FormCtx.ListSchema.Managers.Id + 
    "_$ClientPeoplePicker"];

  var user = {
     EntityType:"User", 
     IsResolved:false, //I've tried true here also
     Key:manager
  };

  peoplePicker.AddUnresolvedUser(user, false); //also tried true
  /*also tried or different variations like this:
  peoplePicker.AddUserKeys(manager);
  peoplePicker.AddUnresolvedUser(true);
  */
}
  • For anyone interested, I couldn't figure out how to tie in the manager lookup during the PreSaveAction so instead I am doing it during the Nominee OnUserResolved event instead. Now when a user adds a new Nominee it kicks off the lookup of that Nominees manager immediately and populates the Manager people picker. This seems to work just fine. – Michael Kubala Oct 6 '18 at 3:10
  • For those that want it in the PreSaveAction, you need to use promises here. It's not getting done with finding the manager and immediately returning true in the presaveaction function--as you mentioned. – Mike Oct 6 '18 at 16:35
1

We can use REST API to get the user's manager, then fill to the Managers field.

The following code for your reference.

<script src="//code.jquery.com/jquery-3.1.0.min.js" type="text/javascript"></script>
<script type="text/javascript">
function PreSaveAction() {
    PopulateManager();
    return true;
}
function PopulateManager() {
    var nominees = $(".sp-peoplepicker-userSpan[id*='Nomination_x0028_s_x0029']");
    $.each(nominees, function(index,value){
        var username = $(value).attr("sid").split("|")[1];
        var manager=getUserManager(username);
        SetAndResolvePeoplePicker("Managers", manager);    
    });
}
function getUserManager(username){
    var manager="";
    var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/SP.UserProfiles.PeopleManager/GetUserProfilePropertyFor(accountName=@v,propertyName='Manager')?@v='"+username+"'";
    $.ajax({
         url: requestUri,
         method: "GET",
         async:false,
         headers: { "Accept": "application/json; odata=verbose" },
         success: function (data) {
            manager = data.d.GetUserProfilePropertyFor;         
         },
         error: function (data) {
         }
     });
    return manager;
}
function SetAndResolvePeoplePicker(fieldName, userName) {
    var _PeoplePicker = $("div[title='" + fieldName + "']");
    var _PeoplePickerTopId = _PeoplePicker.attr('id');
    var _PeoplePickerEditer = $("input[title^='" + fieldName + "']");
    _PeoplePickerEditer.val(userName);
    var _PeoplePickerOject = SPClientPeoplePicker.SPClientPeoplePickerDict[_PeoplePickerTopId];
    _PeoplePickerOject.AddUnresolvedUserFromEditor(true);
}
</script>
  • Very handy. So the trick is to set Async to False in the REST call? Thanks. – Michael Kubala Oct 8 '18 at 15:04
  • Yes, set Async to false to solve the issue. – LZ_MSFT Oct 9 '18 at 1:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.