Friday, December 19, 2014

SharePoint 2013 JavaScript Copy List Item

I have a SharePoint 2013 custom list based form with 160 fields where there is a need to template list items and copy those items as new items.  I could have used SSOM since my solution is for an on-premise implementation but I prefer to use JSOM especially since my client wants the ability to move this solution to the O365 in the future.  MS documentation was helpful on using JSOM to manipulate list items but of course it didn't get into copying items.  I couldn't find any posts specific for the copy list item topic from others other than some related clues on stackoverflow.  The SSOM technique for copying list items was the starting point for this solution and was helpful but it wasn't as easy as finding an alternative JSOM object to the SSOM object.  So through a days worth of hit and miss and a lot of debugging, here is my JSOM code to copy a SharePoint 2013 list item.  I created a custom JSLink view of this list where I override the "Title" field with a "New from Template" button.

//Called from JSLink field override on the Title field, add new request button which will copy this template list item
function GetTemplateLink(ctx) {
    var ret;
    //get id of this item
    var srfID = ctx.CurrentItem.ID;
    ret = TemplateLink(srfID);
    return ret;
function TemplateLink(item_id) {
    //when user clicks button, copy of this item will be created and open in a new window in Edit mode
    return "<input type='button' value='New Request' onclick='jsNewFromTemplate(" + item_id.toString() + ",true);' title='New Request Form' class='clsFormButton' style='width:80px;'/> ";

var tempctx, tempItem, fieldCollection, tempList;

//load the list, the field collection for this list, and the item
function jsNewFromTemplate(id, isTemplate) {
    tempctx = SP.ClientContext.get_current();
    this.web = tempctx.get_web();
    tempList = web.get_lists().getByTitle('Study Request');
    fieldCollection = tempList.get_fields();
    tempItem = tempList.getItemById(id);
    tempctx.executeQueryAsync(Function.createDelegate(this, this.createListItem), Function.createDelegate(this, this.createListItemFail));
//create a new item and load it
function createListItem(sender, args) {
    var itemCreateInfo = new SP.ListItemCreationInformation();
    this.oListItem = tempList.addItem(itemCreateInfo);
    tempctx.executeQueryAsync(Function.createDelegate(this, this.copyListItem), Function.createDelegate(this, this.createListItemFail))
//copy field values from original item into the new item
function copyListItem(sender, args) {
    this.newListItem = tempList.getItemById(oListItem.get_id());
    //customize title with unique ID
    newListItem.set_item('Title', '8' + oListItem.get_id());
    //enumerate the list fields and update values
    var fieldEnumerator = fieldCollection.getEnumerator();
    while (fieldEnumerator.moveNext()) {
        var oField = fieldEnumerator.get_current();
        //exclude fields
        if ((!oField.get_readOnlyField())
            && (oField.get_internalName() != "Attachments")
            && (!oField.get_hidden())
            && (oField.get_internalName() != "Title")
            && (oField.get_internalName() != "ContentType"))
            //get value of source field
            var sourceVal = tempItem.get_item(oField.get_internalName());
            if (sourceVal != null)
                //set value on new item
                newListItem.set_item(oField.get_internalName(), sourceVal);
    tempctx.executeQueryAsync(Function.createDelegate(this, this.showForm), Function.createDelegate(this, this.createListItemFail))
//open copied item in editform.aspx
function showForm(sender, args) {
    var newsrfID = newListItem.get_id();
    var win =, newsrfID), '', 'left=10,top=10,width=1000,height=800,toolbar=1,resizable=1,scrollbars=1,status=1');
function createListItemFail(sender, args) {
    alert('Request failed. ' + args.get_message() +
        '\n' + args.get_stackTrace());
//function to get edit form
function CreateFormUrl(ctx, linkID) {
    var titleUrl = [];
    return titleUrl.join('');