1

I try to use HTML + JQuery in CEWP to build some sort of analog of InfoPath's repeating table in order to be able to insert multiple items in a Sharepoint list using CSOM.

The current task is to get the IDs of inserted items (in order to use those IDs later to add attachments to the list items) as soon as they are added to the list. I've tried several ways but couldn't get the IDs of all inserted items. Usually I get "-1" as an ID for every item except the last one, which returns me the correct ID.

Bellow is the code.

<script src="/testsite1/SiteAssets/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="/testsite1/SiteAssets/jquery.SPServices.min.js" type="text/javascript"></script>

<script type="text/javascript">

    $(document).ready(function() {
        var click = 1;
        $("#btn_id_1").click(function() {
            click ++;
            $("#tr_id_1").clone().appendTo("#tbl_id_1").attr("id", "tr_id_" + click.toString()).find("input").val("");
            });
        $("#btn_id_2").click(function() {
            Save();
            });
        });

    function Save() {

        var ctx = new SP.ClientContext.get_current();
        var taskList = ctx.get_web().get_lists().getByTitle('Tasks');
        var taskItemInfo = new SP.ListItemCreationInformation();
        var vendor;
        var certname;
        var certid;

        $("#tbl_id_1 tr").each(function() {

            vendor = ($(this).find(".vendor")).val();
            certname = ($(this).find(".certname")).val();
            certid = ($(this).find(".certid")).val();

            newTask = taskList.addItem(taskItemInfo);
            newTask.set_item('Title', vendor);
            newTask.set_item('Request_', certname);
            newTask.set_item('h', certid);
            newTask.update();

            ctx.load(newTask);
            ctx.executeQueryAsync(addTaskSuccess, addTaskFailure);
            //timeout();

            function timeout() {
                alert ("!!!");
                //setTimeout(timeout, 5000);
                }

            function addTaskSuccess(sender, args) {
                //console.log(newTask.get_id());
                alert(newTask.get_id());
                //AddAttachment(newTask.get_id())
                }

            function addTaskFailure(sender, args) {
                alert(newTask.get_id());
                //alert("no");
                }       

            });

        window.location = window.location.pathname;

        }

    </script>

    <div id="div_id_1" class="div_class_1">
        <table id="tbl_id_1">
            <tbody>
                <tr id="tr_id_1">
                    <td>Vendor:<br><input type="text" class="vendor" /></td>
                    <td>Cert. Name:<br><input type="text" class="certname" /></td>
                    <td>Cert. ID:<br><input type="text" class="certid" /></td>
                    <td>Attachment:<br><input type="file" class="attachment" /></td>
                </tr>
            </tbody>
        </table>
        <div><button id="btn_id_1" type="button" width="10" height="10">+</button></div>
        <div><button id="btn_id_2" type="button">Save</button></div>
    </div>

1 Answer 1

2

The problem with you code is that you are using the same SP.ClientContext object to make different concurrent requests with ExecuteQueryAsync. In this case your responses become corrupt, as a result you receive incorrect Task Id's. You can try three options:

  1. Inside JQuery each handler construct a new SP.ClientContext object instance and work with it like

    $("#tbl_id_1 tr").each(function() {
       var ctx2 = new SP.ClientContext(ctx.get_url());
       ...
    });
    
  2. You can try add all task list items into an array. After that, make one call to ExecuteQueryAsync. And all your task IDs should be loaded to array items. Have not tried that, but this would be more efficient. Something like:

    var array = [];
    $("#tbl_id_1 tr").each(function() {
       ...
       ctx.load(newTask);
       array.push(newTask);
       ...
    });
    ctx.executeQueryAsync(addTaskSuccess, addTaskFailure);
    ....
    function addTaskSuccess(sender, args) {
        for (i=0; i<array.length; i++) {
            alert(array[i].get_id())
        }
    }
    
  3. Sometimes when you want to make concurrent calls and wait when all of them are over it is useful to implement JQuery $.Deferred/promise technique with $.when.apply.done. It works very well. Here is the sample:
    http://sharepointfieldnotes.blogspot.com/2013/10/sharepoint-2013-rest-code-tips.html Section: Call multiple asynchronous functions and wait for them all to complete (note, that in this sample author is also using the same SP.ClientContext object, that could cause problems).

1
  • ECM4D, thanks for both of sultions about array and promise. Commented Apr 2, 2015 at 4:16

Your Answer

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

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