Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

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...

share|improve this question

2 Answers 2

up vote 1 down vote accepted

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();
        });     
      }
share|improve this answer
    
Thank you for the answers. I will try it and inform you guys the result.. –  dennyw Jun 4 at 7:54
    
Worked like a charm...thanks again. –  dennyw Jun 4 at 8:09

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());
  }
);
share|improve this answer
    
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 Jun 4 at 8:31

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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