0

I have been working on a project for quite some time now. I have found this post somewhat useful, but am unsure if it is correct or not for my utilization.

Functionality:

  • Read in SharePoint list items from 8 different subsites with a GET request.
  • Populate those items in an orderly(grouped) fashion in a DataTable on a single landing page.
  • DataTable has collapsible/expandable rows grouped by program, followed by deliverable.
  • Dropdown menu with buttons to print/excel/PDF/Update the table.
  • Update Table has a HTML form that sends data back to the SharePoint List correlated with the FORM input.

I am currently using 8 different subsites where all of the lists are located. I want to send the new item to the correct list based off of its "Program" value because each of the different lists are a different program. I know I would have to use an if/else statement, but how would I go about that with an AJAX call?

Here is my JS "POST" Code:

$("#btn").click(function(e) {
            PostItem();
        });
    });
    
        function PostItem() {
            return getFormDigest("https://baseurl.sharepoint.com/sites/Projects/USMC/AMMO/Lists/AMMODeliverables/").then(function(digestData) {
                console.log(digestData.d.GetContextWebInformation.FormDigestValue);
                var item = {
                    "__metadata": { "type": "SP.Data.AMMODeliverablesListItem" },
                    "Title": "updated title",
                    "Program": $("#dProgram").val(),
                    "Deliverable": $("#dDeliverable").val(),
                    "To": $("#dTo").val(),
                    "Date": $("#dDate").val(),
                    "Approved": $("#dApproved").val(),
                    "Notes": $("#dNotes").val()
                };

                
                $.ajax({
                    async: true, // Async by default is set to “true” load the script asynchronously  
                    // URL to post data into sharepoint list  or your own url
                    url: "https://baseurl.sharepoint.com/sites/Projects/USMC/AMMO/_api/web/lists/getbytitle('AMMO Deliverables')/items",
                    method: "POST", //Specifies the operation to create the list item  
                    data: JSON.stringify(item),
                    headers: {
                        "content-type": "application/json;odata=verbose",
                        "X-RequestDigest": digestData.d.GetContextWebInformation.FormDigestValue,
                        "Accept": "application/json;odata=verbose",
                        "If-Match": "*"
                    },
                    success: function(data) {
                        alert('Success'); // Used sweet alert for success message
                          console.log(data + " success in updating item");
                    },
                    error: function(data) {
                        alert(JSON.stringify(item));
                        console.log(data);
    
                    }
    
                });
            })
        }
            function getItemTypeForListName(listName) {
                var itemType = "SP.Data." + listName.charAt(0).toUpperCase() + listName.slice(1) + "ListName";
                var encItemType = itemType.replace(/\s/g,'_x0020_');
                return(encItemType);
    }       
        function getFormDigest(baseurl) {
    
            return $.ajax({
    
                url: "https://baseurl.sharepoint.com/sites/Projects/USMC/AMMO/_api/contextInfo",
    
                method: 'POST',
    
                headers: {
                    'Accept': 'application/json; odata=verbose'
                }
    
            });
            }   

To achieve the final goal of my script, would I do something along the lines of:

function PostItem() {
            return getFormDigest("https://gemini3group.sharepoint.com/sites/Projects/USMC/AMMO/Lists/AMMODeliverables/").then(function(digestData) {
                console.log(digestData.d.GetContextWebInformation.FormDigestValue);
                var item = {
                    "__metadata": { "type": "SP.Data.AMMODeliverablesListItem" },
                    "Title": "updated title",
                    "Program": $("#dProgram").val(),
                    "Deliverable": $("#dDeliverable").val(),
                    "To": $("#dTo").val(),
                    "Date": $("#dDate").val(),
                    "Approved": $("#dApproved").val(),
                    "Notes": $("#dNotes").val()
                };

                if (dProgram == "AMMO"){
                    $.ajax({
                        async: true, // Async by default is set to “true” load the script asynchronously  
                        // URL to post data into sharepoint list  or your own url
                        url: "https://siteurl.sharepoint.com/sites/Projects/USMC/AMMO/_api/web/lists/getbytitle('AMMO Deliverables')/items",
                        method: "POST", //Specifies the operation to create the list item  
                        data: JSON.stringify(item),
                        headers: {
                            "content-type": "application/json;odata=verbose",
                            "X-RequestDigest": digestData.d.GetContextWebInformation.FormDigestValue,
                            "Accept": "application/json;odata=verbose",
                            "If-Match": "*"
                        },
                        success: function(data) {
                            alert('Success'); // Used sweet alert for success message
                            console.log(data + " success in updating item");
                        },
                        error: function(data) {
                            alert(JSON.stringify(item));
                            console.log(data);
    
                    }
    
                });
                }
                else if (dProgram == "AHR"){
                    $.ajax({
                        async: true, // Async by default is set to “true” load the script asynchronously  
                        // URL to post data into sharepoint list  or your own url
                        url: "https://siteurl.sharepoint.com/sites/Projects/USMC/AMMO/_api/web/lists/getbytitle('AMMO Deliverables')/items",
                        method: "POST", //Specifies the operation to create the list item  
                        data: JSON.stringify(item),
                        headers: {
                            "content-type": "application/json;odata=verbose",
                            "X-RequestDigest": digestData.d.GetContextWebInformation.FormDigestValue,
                            "Accept": "application/json;odata=verbose",
                            "If-Match": "*"
                        },
                        success: function(data) {
                            alert('Success'); // Used sweet alert for success message
                            console.log(data + " success in updating item");
                        },
                        error: function(data) {
                            alert(JSON.stringify(item));
                            console.log(data);
    
                    }

1 Answer 1

1

First of all, your getFormDigest function is not quite right:

function getFormDigest(baseurl) {
    
    // you pass in a "baseurl" value above, but you're not really doing anything with it.
    // the URL you use below is hardcoded to always
    // make the request to the /sites/Projects/USMC/AMMO site

    return $.ajax({

        url: "https://baseurl.sharepoint.com/sites/Projects/USMC/AMMO/_api/contextInfo",

        method: 'POST',

        headers: {
            'Accept': 'application/json; odata=verbose'
        }

    });
} 

What you need to do is change that so you can pass a site URL into it and get a valid form digest from the actual site you are trying to post a new item to:

function getFormDigest(siteUrl) {
    return $.ajax({
        url: siteUrl + "/_api/contextInfo",
        method: 'POST',
        headers: {
            'Accept': 'application/json; odata=verbose'
        }
    });
}

Next, you need to change your PostItem function to react to the current value of the selected Program, and choose some correct values based on that. You need three different values to be generated dynamically based on the selected Program:

  1. The URL to the site itself so you can get a valid form digest,
  2. The list name, so you can get the correct List Item Entity Type value for your new item's JSON __metadata property. You have a function to do this, but you aren't using it. Also, you'll need the list name for:
  3. A URL that includes the site and the list name so you can post the new list item (since the URL to do that is essentially [URL to site]/_api/web/lists/getbytitle('[list name]')/items)

You could do a sequence of if..then..else if..then..else if..then..else statements, but for more than two or three possible values, that gets cumbersome. A much cleaner way of doing it is using a switch statement. So here's what your PostItem function might look like if you used a switch to evaluate what the selected Program value is and then dynamically set the site URL and list name based on that:

function PostItem() {

    // the base URL should be what is the same across all subsites. in comments
    // on another post you said the subsites start to differ after /sites/Projects.
    var baseUrl = "https://your-tenant.sharepoint.com/sites/Projects";

    // get the selected program from your form
    var programName = $("#dProgram").val();

    var siteUrl = null; // set this as empty for now
    var listName = null; // set this as empty for now

    // a "switch" statement is like a fancy "if" statement that is
    // useful if you have more than just two or three options

    switch (programName) {
        case "AMMO":
            // set the site url to be whatever it is after /sites/Projects.
            // in the case of AMMO, you have already posted that the "AMMO"
            // subsite is under a "USMC" subsite that is under "Projects"
            siteUrl = baseUrl + "/USMC/AMMO";
            listName = "AMMODeliverables";
            break;
        case "AHR":
            // set the site url to be whatever it is after /sites/Projects.
            // IF in this case the "AHR" subsite is directly under /Projects
            // and NOT under another subsite (as is the case with /USMC/AMMO),
            // you just add that directly:
            siteUrl = baseUrl + "/AHR";

            // HOWEVER, if it is under another subsite with a different name, similar
            // to how "AMMO" is actually under another subsite called "USMC", then you
            // would include that "Other" subsite here:
            siteUrl = baseurl + "/Other/AHR";

            // set the list name, since you said the list names
            // are different in each of the subsites
            listName = "AHR Deliverables";
            break;
        case "FOO":
            // pretending that "FOO" is _directly_ under /sites/Projects
            siteUrl = baseurl + "/FOO";
            listName = "FOO Thingys";
            break;
        case "BAR":
            // pretending that "BAR" is NOT directly under /sites/Projects,
            // but is in fact under another "Different" subsite
            siteUrl = baseurl + "/Different/BAR";
            listName = "BAR Whatchamacallits";
        default:
            // all switch statements need a default option in case
            // what we are checking does not match any any of the options
            // we are expecting. in this instance, we will _not_ set
            // a site URL or list name so that we do not try to post
            // to a non-existent site or list
            break;
    }

    // if we didn't get one of our expected choices for programName, then siteUrl
    // will not have been populated in the switch, so we can check and make sure we
    // actually have a valid siteUrl before we start sending AJAX requests out

    if (siteUrl) {

        // pass the siteUrl into your improved getFormDigest function so
        // that you get the correct form digest from the site you are
        // actually trying to post a new item to.
        // also, you don't actually need the "return" here.

        getFormDigest(siteUrl).then(function(digestData) {
            console.log(digestData.d.GetContextWebInformation.FormDigestValue);

            // use your existing getItemTypeForListName function to get the
            // correct SharePoint List Item Entity Type name based on
            // the list name
            
            var listItemEntityType = getItemTypeForListName(listName);

            // construct the URL to post the new list item to based on the siteUrl
            // and the listName, which vary based on the selected projecName

            var postNewItemUrl = siteUrl + "/_api/web/lists/getbytitle('" + listName + "')/items";

            // construct your new item JSON.  you said in another post that all 
            // the fields in all the lists are the same, so the only thing that 
            // really needs to dynamically change here is the entity type name,
            // which was generated based on the list name

            var item = {
                "__metadata": { "type": listItemEntityType },
                "Title": "updated title",
                "Program": programName,
                "Deliverable": $("#dDeliverable").val(),
                "To": $("#dTo").val(),
                "Date": $("#dDate").val(),
                "Approved": $("#dApproved").val(),
                "Notes": $("#dNotes").val()
            };

            
            $.ajax({ 
                // use your dynamically generated URL here
                url: postNewItemUrl,
                method: "POST",  
                data: JSON.stringify(item),
                headers: {
                    "content-type": "application/json;odata=verbose",
                    "X-RequestDigest": digestData.d.GetContextWebInformation.FormDigestValue,
                    "Accept": "application/json;odata=verbose",
                    "If-Match": "*"
                },
                success: function(data) {
                    alert('Success'); // Used sweet alert for success message
                    console.log(data + " success in updating item");
                },
                error: function(data) {
                    alert(JSON.stringify(item));
                    console.log(data);

                }

            });
        });
    }
}
4
  • Hey, so I just updated my code, and it looks amazing and should be functiona but it is giving me a status 404 error that the site doesn't exist? I changed this jsfiddle.net/y5hea8j9
    – BeerusDev
    Sep 30, 2020 at 12:56
  • And I was quick to figure out that issue, but I fixed it it was the listname for AHR and AMMO were mixed up, but now it gives me a 400 error
    – BeerusDev
    Sep 30, 2020 at 12:59
  • I think I figured out what the error is but don't understand a solution.. SP.Data.AHRDeliverablesListItem is what is expected by sharepoint, and this is what is being showed in the console with the request payload "SP.Data.AHR_x0020_DeliverablesListName"
    – BeerusDev
    Sep 30, 2020 at 13:19
  • Disregard, I was able to fix the errors had a few logic errors
    – BeerusDev
    Sep 30, 2020 at 14:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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