This project has moved. For the latest updates, please go here.

Uncaught TypeError: Cannot read property 'GetAllUserInfo' of undefined \\ SPFIeldUserMulti SP2013

Dec 25, 2015 at 7:01 AM
Edited Dec 25, 2015 at 7:03 AM
Hi, thanks for your library. But i'v got issue when i try my SPFIeldUserMulti make read only.

i'm doing somethink like this:

SPUtility.GetSPField("PeopleField").MakeReadOnly();

the problem is that ClientPeoplePicker is undefined in your parameters class.

when i try to execute this part in your library i receive this error:
   SPField.prototype.MakeReadOnly = function () {
      return this._makeReadOnly(this.GetValue().toString());
   };
   SPUserField2013.prototype.GetValue = function () {
      return this.ClientPeoplePicker.GetAllUserInfo();
   };
because this.ClientPeoplePicker is undefined. i cant execute function GetAllUserInfo() if ClientPeoplePicker is undefined.

do you have some ideas?
Dec 25, 2015 at 7:25 AM
Edited Dec 25, 2015 at 7:47 AM
i found the source of the problem. its' here:
function SPUserField2013(fieldParams) {
      SPField.call(this, fieldParams);
      
      if (this.Controls === null) {
         return;
      }

      // sharepoint 2013 uses a special autofill named SPClientPeoplePicker
      // _layouts/15/clientpeoplepicker.debug.js
      var pickerDiv = $(this.Controls).children()[0];
      __this.ClientPeoplePicker = window.SPClientPeoplePicker.SPClientPeoplePickerDict[$(pickerDiv).attr('id')];__
      this.EditorInput = $(this.Controls).find("[id$='_EditorInput']")[0];
      //this.HiddenInput = $(this.Controls).find("[id$='_HiddenInput']")[0];
      //this.AutoFillDiv = $(this.Controls).find("[id$='_AutoFillDiv']")[0];
      //this.ResolvedList = $(this.Controls).find("[id$='_ResolvedList']")[0];
   }
when i tried to debug this i get this.ClientPeoplePicker === 'undefined'
after this js command: this.ClientPeoplePicker = window.SPClientPeoplePicker.SPClientPeoplePickerDict[$(pickerDiv).attr('id')];

in pickerDiv i have this:
<div>
     my default people picker field with my id
</div>
so this $(pickerDiv).attr('id') just cant find my id because of this.

my real div with people picker is nested in some other div which added with jslink. i overwrote my default design of field and it stopped working.

to make it work i added this:
var pickerDiv = $(this.Controls).find('.sp-peoplepicker-topLevel')[0];
BUT, here's another problem. Instead of viewing my data which i inserted i see something like this:

PeopleField: [object Object],[object Object]
Dec 25, 2015 at 7:54 AM
okey, now understood that this._makeReadOnly(this.GetValue() returns my data in object format.
   SPField.prototype.MakeReadOnly = function () {
      return this._makeReadOnly(this.GetValue().toString());
   };
well, dunno how it could be simply converted to string format. :) did it ever worked with spFIeldUserMulti? :D
Dec 26, 2015 at 5:25 PM
Edited Dec 26, 2015 at 5:39 PM
okey, guys. I know it's just me here, who knows if somebody would ever read this and it could somehow to help him. I will post here my solution:
    function SPUserField2013(fieldParams) {
        SPField.call(this, fieldParams);

        if (this.Controls === null) {
            return;
        }

        // sharepoint 2013 uses a special autofill named SPClientPeoplePicker
        // _layouts/15/clientpeoplepicker.debug.js

        //var pickerDiv = $(this.Controls).children()[0]; ORIGINAL  <-----------------
        var pickerDiv = $(this.Controls).children().find('.sp-peoplepicker-topLevel')[0]; //CHANGED <-----------------

        this.ClientPeoplePicker = window.SPClientPeoplePicker.SPClientPeoplePickerDict[$(pickerDiv).attr('id')];
        this.EditorInput = $(this.Controls).find("[id$='_EditorInput']")[0];
        //this.HiddenInput = $(this.Controls).find("[id$='_HiddenInput']")[0];
        //this.AutoFillDiv = $(this.Controls).find("[id$='_AutoFillDiv']")[0];
        //this.ResolvedList = $(this.Controls).find("[id$='_ResolvedList']")[0];
    }
plus added a new prototype for SPUserField2013 (of course this applies only SP2013):
   SPUserField2013.prototype.MakeReadOnly = function (value) {
        var tmpArray = new Array();

        $.each(this.GetValue(), function (key, val) {
            if (val['Key'] != null) { tmpArray.push(val['Key']) }
        });

        var SPUserField = this;


        var x = getUserId(tmpArray, SPUserField);

        x.done(function (result) {
            // result is an SP.List because that is what we passed to resolve()!
            var htmlText = "";
            for (i = 0; i < result.users.length; i++) {
                var user = result.users[i];
                if (htmlText != "") { htmlText += "; "; }
                htmlText += '<a href="/_layouts/15/userdisp.aspx?ID=' + user.get_id().toString() + '&amp;RootFolder=*">' + user.get_title() + '</a>';
            }

            return result.SPUserField._makeReadOnly(htmlText);

        });
        x.fail(function (result) {
            // result is a string because that is what we passed to reject()!
            var error = result;
            console.log(error);
        });



        function successCallback(d) {
            var o = { users: this.users, SPUserField: this.SPUserField };
            this.d.resolve(o);
        }

        function failCallback() {
            this.d.reject("Something went wrong...");
        }


        function getUserId(loginNames, SPUserField) {
            var d = $.Deferred();
            var context = new SP.ClientContext.get_current();

            var arrayLength = loginNames.length;
            var users = new Array();

            for (var i = 0; i < arrayLength; i++) {
                var user = context.get_web().ensureUser(loginNames[i]);
                context.load(user)
                users.push(user);
            }

            var o = { d: d, loginNames: loginNames, users: users, SPUserField: SPUserField };
            context.executeQueryAsync(Function.createDelegate(o, successCallback), Function.createDelegate(o, failCallback));
            return d.promise();
        };        

    };
I wouldn't say it's clean, but it work's as regular people picker field in display mode, with workable hyperlinks of users. if someone would make more clean, contact me.

cheers.