2

Hi Sharepoint experts,

I'm trying to add list item using jsom and succeeded but my code keeps adding empty list item first.

    function repeat(pattern, count) {
        if (count < 1) return '';
        var result = '';
        while (count > 1) {
            if (count & 1) result += pattern;
            count >>= 1, pattern += pattern;
        }
        return result + pattern;
    }

    function onCountSucceeded() {
        varNoPR = '';
        varListCnt = oList.get_itemCount();
        if (varListCnt === 0) {
            varListCnt = 1;
        }
        else {
            varListCnt += 1;
        }
        varTmpStr = varListCnt.toString();
        varStrLen = varTmpStr.length;
        varNoPR = repeat('0', 10 - varStrLen).concat(varTmpStr);
     }

    function getLastNumber() {
        var clientContext2 = new SP.ClientContext(varsiteUrl);
        this.oList = clientContext2.get_web().get_lists().getByTitle(listName);
        clientContext2.load(this.oList);    
        clientContext2.executeQueryAsync(
            Function.createDelegate(this, this.onCountSucceeded),
            Function.createDelegate(this, this.onQueryFailed)
        );    
    }

    function createItem() {  
        var clientContext = new SP.ClientContext(varsiteUrl);
        var oList = clientContext.get_web().get_lists().getByTitle(listName);

        var itemCreateInfo = new SP.ListItemCreationInformation();
        this.oListItem = oList.addItem(itemCreateInfo);
        oListItem.set_item('Title', 'My New Item!');
        oListItem.set_item('NoPR', varNoPR);
        oListItem.update();

        clientContext.load(oListItem);
        clientContext.executeQueryAsync(
            Function.createDelegate(this, this.onAddItemSucceeded),
            Function.createDelegate(this, this.onQueryFailed)
        );
    }

    function createListItem() {
        getLastNumber();
        createItem();
    }

So my goal is inserting custom auto increment number by counting the list items first and then add '0' so the resulting number becomes '0000000001', ...etc. But when I run this twice (I assigned this code to button), it resulted in empty item, and then item 0000000001. What I am doing wrong here ?

Thanks for any help...

2 Answers 2

1

The problem is that the calls are async, so you should make sure getLastNumber() is done before you call createItem(). This could be done in diferrent ways, but an easy route is to use jQuerys $.Deferred object.

An simple example based on your getLastNumber and createListItem:

function getLastNumber() {
        this.dfd = $.Deferred();

        var clientContext2 = new SP.ClientContext(varsiteUrl);
        this.oList = clientContext2.get_web().get_lists().getByTitle(listName);
        clientContext2.load(this.oList);    
        clientContext2.executeQueryAsync(
            Function.createDelegate(this, this.onCountSucceeded),
            Function.createDelegate(this, this.onQueryFailed)
        );    

        return this.dfd.promise();
    }

   function onCountSucceeded() {
    varNoPR = '';
    varListCnt = oList.get_itemCount();
    if (varListCnt === 0) {
        varListCnt = 1;
    }
    else {
        varListCnt += 1;
    }
    varTmpStr = varListCnt.toString();
    varStrLen = varTmpStr.length;
    varNoPR = repeat('0', 10 - varStrLen).concat(varTmpStr);

    this.dfd.resolve();
 }


      function createListItem() {
         getLastNumber().done(function() {
           createItem();
        });     
      }
1
  • Thank you for the answers. I will try it and inform you guys the result..
    – dennyw
    Commented Jun 4, 2014 at 7:54
1

Welcome to the SharePoint SE!

This behavior occurs since SP.ClientContext.executeQueryAsync method is an async method. Hence you cant call your methods sequentially like this:

getLastNumber();
createItem();

but have to wait until succeededCallback function will be invoked and only then execute the next request.

When working with asynchronous API such as JSOM the following patterns are commonly used:

  • Using nested callbacks
  • Using the promises pattern

Please refer Asynchronous programming in apps for Office article to get acquainted with asynchronous programming for SharePoint.

The below example is converted version of your example using callback approach:

function repeat(pattern, count) {
        if (count < 1) return '';
        var result = '';
        while (count > 1) {
            if (count & 1) result += pattern;
            count >>= 1, pattern += pattern;
        }
        return result + pattern;
}




function getNextNumber(listTitle,OnSuccess,OnError) {
    var context = SP.ClientContext.get_current();
    var list = context.get_web().get_lists().getByTitle(listTitle);
    context.load(list);    
    context.executeQueryAsync(
        function(){
               var nextIdStr = (list.get_itemCount() + 1).toString();
               var nextNoPR = repeat('0', 10 - nextIdStr.length).concat(nextIdStr);
               OnSuccess(nextNoPR);
        },
        OnError
    );    
}





function addListItem(listTitle,itemProps,OnItemAdded,OnItemFailed)
{
    var context = SP.ClientContext.get_current();
    var web = context.get_web();

    var list = web.get_lists().getByTitle(listTitle);
    var itemCreateInfo = new SP.ListItemCreationInformation();
    var listItem = list.addItem(itemCreateInfo);

    for(var propName in itemProps) {
       listItem.set_item(propName, itemProps[propName]) 
    }

    listItem.update();
    context.load(listItem);
    context.executeQueryAsync(
        function() {
          OnItemAdded(listItem);           
        },
        OnItemFailed
    );
}

Usage

var listTitle = 'Requests';
getNextNumber(listTitle,
  function(nextNoPR){
      //console.log(nextNoPR);

      var itemProperties  = {'Title': 'New request','NoPR':nextNoPR};
      addListItem(listTitle,itemProperties,
         function(item){   
            console.log(item.get_item('NoPR'));
         },
         function(sender,args){
            console.log(args.get_message());
         }
      );
  },
  function(sender,args){
      console.log('An error corrured while getting next NoPR:' + args.get_message());
  }
);
1
  • this one works too. but I can't use SP.ClientContext.get_current(). I kept my new SP.ClientContext(varsiteUrl) to make it work.
    – dennyw
    Commented Jun 4, 2014 at 8:31

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.