List or Library Control for Document Libraries

Hello all.

I've been working on changing some of our forms, moving away from SP List "attachments" and toward Document Library uploads.

On this form, I have four List or Library controls: Comments (Discussion List), StemMediaUpload (DL), OptionsMediaUpload (DL), and ReferenceMediaUpload (DL). The only one that works is the List-to-List (Comments).

SUCCESS
Passing values from a Parent SP List to a Child SP List as shown in the Discussion illustration below here.

CODE FOR LIST (works)

//Populate fields of a new List or Library record with the values from the parent form
fd.spRendered(function() {
    //prepopulating fields of a new List or Library record with the values from the parent form
    fd.control('Comments').$on('edit', function(editData) {
        //Check that this is a new record
        if (editData.formType === 'New') {
            //Prepopulating Commentor field
            editData.field('Commentor').ready(function() {
                editData.field('Commentor').value = fd.field('WriterTxt').value;
            });
        }
    });
});

PROBLEM
I can't pass all values from a Parent SP List to a Child SP Document Library. I have tried a variation of this with no luck. I have also tried many other combinations. I know I missing something fundamental as my values do not pass from Parent to Child. UPDATE: I have childMediaType working now but not the other two columns.

I welcome any wisdom here. Many thanks as always.

UPDATE: I was getting confused with the column names the same in the List and DL. I have made some changes to differentiate between the Parent and Child.

ADDED INFORMATION

  • Parent List (on same SP site as DL)

    • typeStemMedia - Choice (Fixed: was MediaType in my initial post)
    • WriterName - Person or group
    • Specialty - Lookup (from List on same SP site as DL & Parent List)
  • Child Document Library (on same SP site as List)

    • childMediaType - Choice (Fixed: was MediaType in my initial post)
    • childwriterName - Person or group (Fixed: was WriterName in my initial post)
    • childSpecialty - Lookup (from List on same SP site as DL & Parent List; Fixed: was Specialty in my initial post)

The Discussion illustration from above is a parent-to-child list workflow and works as desired. The video illustration below is a parent-to-child document library workflow, where two of the three targeted child fields (childwriterName and childSpecialty) fail to populate.

VIDEO ILLUSTRATION

CODE FOR DOCUMENT LIBRARY (does not work)

//Populate fields of a new List or Library record with the values from the parent form
fd.spRendered(function() {
    //prepopulating fields of a new List or Library record with the values from the parent form
    fd.control('StemMediaUpload').$on('edit', function(editData) {
        //var currentUserName = _spPageContextInfo.userDisplayName; is used in a previous block to set the value of 'WriterTxt' to be available for use here
        //Check that this is a new record
        if (editData.formType === 'New') {
            //Prepopulating WriterName field; WriterTxt already populated from Parent List WriterName value
            editData.field('WriterName').ready(function() {
                editData.field('WriterName').value = fd.field('WriterTxt').value;
            });
        }
    });
});

TROUBLESHOOTING HISTORY UPDATE: I have made adjustments to column names since the initial post so some of these may be out of date. As shown in this example, I have tried replacing any reference to edit with upload and New to Add. Basically, attempting to make SOMETHING work or change to help me understand what is/isn't working.

Tried this:

//Populate fields of a new List or Library record with the values from the parent form
fd.spRendered(function() {
    //prepopulating fields of a new List or Library record with the values from the parent form
    fd.control('StemMediaUpload').$on('upload', function(filesUploaded) {
        //Check that this is a new record
        if (editData.formType === 'Add') {
            //Populate MediaType field
            editData.field('Specialty').ready(function() {
                editData.field('Specialty').value = fd.control('Specialty').value;

            });
        }
    });
});

Also tried:

var listOrLibrary = 'StemMediaUpload';
var docLibraryTitle = 'Stem Media';

fd.spRendered(function() {
    fd.control(listOrLibrary).$on('filesUploaded',
        function(itemIds) {
            //get document library by Title
            var library = pnp.sp.web.lists.getByTitle(docLibraryTitle);
            //go through each uploaded Item Id and set field values
            library.getListItemEntityTypeFullName().then(function(entityTypeFullName){

                var batch = pnp.sp.web.createBatch();

                for(var i = 0; i < itemIds.length; i++){
                    //specify which fields to update and how
                    library.items.getById(itemIds[i]).inBatch(batch).update({
                        WriterName: fd.field('WriterName').value.LookupValue,
                        Specialty: fd.field('Specialty').value.LookupValue,
                        MediaType: fd.field('MediaType').value.LookupValue
                    }, "*", entityTypeFullName);
                }

                batch.execute().then(function(){
                    fd.control(listOrLibrary).refresh();
                });
            });
        });
});

And this section based on this post:

                    WriterName: fd.field('WriterName').value.EntityData.SPUserID,
                    Specialty: fd.field('Specialty').value.LookupID,
                    MediaType: fd.field('MediaType').value.LookupID
                }, "*", entityTypeFullName);
            }

And this based on this post:

var listOrLibrary = 'StemMediaUpload';
var docLibraryTitle = 'Stem Media';

fd.spRendered(function() {
    var writerNameId = fd.field('WriterName').value.LookupId;
    var specialtyId = fd.field('Specialty').value.LookupId;
    var mediaTypeId = fd.field('MediaType').value.LookupId;
    fd.control(listOrLibrary).$on('filesUploaded',
        function(itemIds) {
            //get document library by Title
            var library = pnp.sp.web.lists.getByTitle(docLibraryTitle);
            //go through each uploaded Item Id and set field values
            library.getListItemEntityTypeFullName().then(function(entityTypeFullName){

                var batch = pnp.sp.web.createBatch();

                for(var i = 0; i < itemIds.length; i++){
                    //specify which fields to update and how
                    library.items.getById(itemIds[i]).inBatch(batch).update({
                        //WriterName: fd.field('WriterName').value.EntityData.SPUserID
                        WriterName: writerNameId,
                        //Specialty: fd.field('Specialty').value.LookupID,
                        Specialty: specialtyId,
                        //MediaType: fd.field('MediaType').value.LookupID
                        MediaType: mediaTypeId
                    }, "*", entityTypeFullName);
                }

                batch.execute().then(function(){
                    fd.control(listOrLibrary).refresh();
                });
            });
        });
});

@shedev,

For Person or Group and Lookup fields, you need to add Id suffix to the internal name of the field:
WriterNameId
SpecialtyId

And you need to get data of the fields depending on its type:

//person or group, get user ID
    var writerNameId = fd.field('WriterName').value.EntityData.SPUserID;
//lookup
    var specialtyId = fd.field('Specialty').value.LookupId;
//single choice
    var mediaTypeId = fd.field('MediaType').value;

And this is the code you need to use to update document details. Update field names before testing.

var listOrLibrary = 'ListOrLibrary1';
var docLibraryTitle = 'Documents';

fd.spRendered(function() {
    fd.control(listOrLibrary).ready().then(function(dt) {
        dt.$on('filesUploaded',
            function(itemIds) {
                //get document library by Title
                var library = pnp.sp.web.lists.getByTitle(docLibraryTitle);
                //go through each uploaded Item Id and set field values
                library.getListItemEntityTypeFullName().then(function(entityTypeFullName) {

                    var batch = pnp.sp.web.createBatch();

                    for (var i = 0; i < itemIds.length; i++) {
                        //specify which fields to update and how
                        library.items.getById(itemIds[i]).inBatch(batch).update({
                            Choice: fd.field('Choice').value,
                            LookuptId: fd.field('Lookup').value.LookupId,
                            PersonId: fd.field('Person').value.EntityData.SPUserID
                        }, "*", entityTypeFullName);
                    }

                    batch.execute().then(function() {
                        dt.refresh();
                    });
                });
            });
    });
});

@mnikitina - thank you for this guidance. I have one of the fields populating now and struggle to get the others to grab values. This is what I have in place currently but have tried so many variations with no success other than setting the choice field.

What am I not understanding? I made notes as to what I think I know about each line but I wonder if there is something else I am missing.

Document Library (child)
SPDocLibCols

List (Parent)
ListCols

fd.spRendered(function() {

//Child DL Column + ID / SharePoint Person or group, get user ID
    var childwriterNameId = fd.field('WriterName').value.EntityData.SPUserID;

//Child DL Column + ID / SharePoint Lookup
    var childSpecialtyId = fd.field('Specialty').value.LookupId;

//SharePoint Choice (so far only this piece is working)
    var childMediaType = fd.field('typeStemMedia').value;

//Plumsail Control name (mine is a string with no spaces)
    var listOrLibrary = 'NameofPlumsailControlHere';
    
//Document Library name (mine is a string WITH spaces)
    var docLibraryTitle = "Name of Document Library Here";   
    
    
    fd.control(listOrLibrary).ready().then(function(dt) {
        dt.$on('filesUploaded',
            function(itemIds) {
                //get document library by Title
                var library = pnp.sp.web.lists.getByTitle(docLibraryTitle);
                //go through each uploaded Item Id and set field values
                library.getListItemEntityTypeFullName().then(function(entityTypeFullName) {

                    var batch = pnp.sp.web.createBatch();

                    for (var i = 0; i < itemIds.length; i++) {
                        //specify which fields to update and how

    
                        library.items.getById(itemIds[i]).inBatch(batch).update({
                            //Child Document Library Column var: Parent SharePoint List Column
                            childMediaType: fd.field('typeStemMedia').value,
                            
                            //Child Document Library Column var: Parent SharePoint List Lookup Column
                            childSpecialtyId: fd.field('Specialty').value.LookupId,
                            
                            //Child Document Library Column var: Parent SharePoint List Person or group Column
                            childwriterNameId: fd.field('WriterName').value.EntityData.SPUserID

                            
                            /* Notes from Margarita Nikitina
                            Choice: fd.field('Choice').value,
                            LookupId: fd.field('Lookup').value.LookupId,
                            PersonId: fd.field('Person').value.EntityData.SPUserID
                            */
                            
                            
                            
                        }, "*", entityTypeFullName);
                    }

                    batch.execute().then(function() {
                        //console.log("Stem Media Uploaded!");
                        dt.refresh();
                    });
                  });
                
            });
        
    });
    
});

@shedev,

Is it a single or multiple choice field? Are there errors in the browser console when uploading files? Please share the screenshot.

@mnikitina,

I finally found a pathway to success. This is a very fussy process and I spent many hours in F12 rabbit holes that did not provide help. In the end, I recreated a new Document Library, new fields, and skipped the Lookup column types - I still have no idea how to make that work. I wish I did but this is a workaround I can apply to the two other DLs I have on my form.

fd.spRendered(function() {

//Plumsail Control name
    var listOrLibrary = 'ControlNameHere';
    
//Document Library name    
    var docLibraryTitle = 'DocumentLibraryNameHere';

    fd.control(listOrLibrary).$on('filesUploaded',
        function(itemIds) {
            //get document library by Title
            var library = pnp.sp.web.lists.getByTitle(docLibraryTitle);
            //go through each uploaded Item Id and set field values
            library.getListItemEntityTypeFullName().then(function(entityTypeFullName){

                var batch = pnp.sp.web.createBatch();

                for(var i = 0; i < itemIds.length; i++){
                    //specify which fields to update and how
                    library.items.getById(itemIds[i]).inBatch(batch).update({
                    childDocLibLookupColumnSpecialty: fd.field('ParentTextFieldNameHere').value,
                    childDocLibPersonColumnWriterNameId: fd.field('ParentPersonFieldNameHere').value.EntityData.SPUserID
                    }, "*", entityTypeFullName);
                }

                batch.execute().then(function(){
                    fd.control(listOrLibrary).refresh();
                });
            });
        });
});

@shedev,

There are many reason for the code doesn't work as intended: wrong internal name, incorrect value, some syntax error. To help you I need to know the errors you see when you uploading documents. Please share the screenshot of all error from the browser console and export of the form.

@mnikitina - I always appreciate your wisdom and insight. Thank you warmly and I apologize for perhaps sounding less than thankful - I was frustrated and certainly no fault of you or plumsail. The product has helped people like me deliver functional software while multitasking in other roles (not developing full time). Again, my deepest thanks for everything you offer.

At this moment, the form works as desired but I can share screenshots in this state too, for a comparison. I see many "spserviceworker.js" and "spform.js" references in the developer tools console. When searching against these terms within the community, I found another common console reference of "[Uncaught (in promise)](Populating user profile properties (Sharepoint 2019) - #11 by Marcin)" that looks to be related to undefined fields. I read this as JavaScript that maybe was written for an intended purpose but abandoned later and not commented out. Does that sound right?

The "spserviceworker.js", "spform.js", and "[Uncaught (in promise)" errors are not preventing the page from load and behaving correctly but I suspect is can slow processes.

The first step when I see an overload of errors is to comment out recent code and check again, then I also look at the browser version to ensure I have the latest update in place.

Something that is very helpful is the Debugger link that jumps directly into the code from the plumsail JS panel and I can see exactly where my code may be faulting.

A nice example of this is shown in the illustration below. When I click on the VM3099:63 hyperlink, the block of code I have in Plumsail Designer is shown and I can see that on Line 63, I have a field that is referenced but not defined. That's what the browser sees anyway. This helps me get right to the location and test.

1 Like

After successfully getting listOrLibrary control to populate the #1 Child Document Library, I added a second for the next DL (2nd of three DLs) on the form. Now the errors are back and the values do not populate the #2 Child Document Library.

fd.spRendered(function() {

//Plumsail Control name
    var listOrLibrary = 'listOrLibraryControlNameHere';
    
//Document Library name    
    var docLibraryTitle = 'ChildDLNameHere';

    fd.control(listOrLibrary).$on('filesUploaded',
        function(itemIds) {
            //get document library by Title
            var library = pnp.sp.web.lists.getByTitle(docLibraryTitle);
            //go through each uploaded Item Id and set field values
            library.getListItemEntityTypeFullName().then(function(entityTypeFullName){

                var batch = pnp.sp.web.createBatch();

                for(var i = 0; i < itemIds.length; i++){
                    //specify which fields to update and how
                    library.items.getById(itemIds[i]).inBatch(batch).update({
                    childDLOptionMediaSpecialty: fd.field('SpecialtyTxt').value,
                    childDocLibOptionPersonColumnWriterNameId: fd.field('PkIdAzure').value.EntityData.SPUserID
                    }, "*", entityTypeFullName);
                }

                batch.execute().then(function(){
                    fd.control(listOrLibrary).refresh();
                });
            });
        });
});

DISCOVERY

The way a Document Library is created matters! Any "Classic" tool or process seems to not work. I created a new DL from an old DL and the mismatched names traveled from old to new.

BeforeAfterColRename

I have now created a new DL from scratch, using the modern method to create columns.