javascriptsharepoint-2010splistitemsplistmicrosoft-ajax

How can I determine if a Sharepoint ListItem exists based on a couple of known values?


I have this Sharepoint (2010) Javascript (adapted from here) to insert or Update various "fields" in the ListItem:

var listId;

. . .

function upsertPostTravelListItemTravelerInfo1() {
  var clientContext = new SP.ClientContext(siteUrl);
  var oList = clientContext.get_web().get_lists().getByTitle('PostTravelFormFields');

  var itemCreateInfo = new SP.ListItemCreationInformation();
  this.oListItem = oList.addItem(itemCreateInfo);

  listId = this.oListItem.ID;
  oListItem.set_item('ptli_formFilledOut', new Date());
  oListItem.set_item('ptli_TravelersName', $('travelername').val());
    . . .

  oListItem.update();

  clientContext.load(oListItem);

  clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}

In the code above, the first "upsert" stores the "listId"; subsequent writes into the list (it is to be written piece-by-piece, in case the user stops or something stops them, and they come back to it later) get that previously begin ListItem using the getItemById() method:

function upsertPostTravelListItemTravelerInfo2() {
  var clientContext = new SP.ClientContext(siteUrl);
  var oList = clientContext.get_web().get_lists().getByTitle('PostTravelFormFields');
  this.oListItem = oList.getItemById(listId);

  oListItem.set_item('ptli_tripNumber', $('tripnumber').val());
    . . .

My challenge is in a case where the user wants to update the first bits of data (they insert those, then come back later and decide to change something) in the first of the two methods shown above (upsertPostTravelListItemTravelerInfo1()).

I will need the use getItemById() here, too. When this is the first entry, it doesn't exist yet, and I use:

listId = this.oListItem.ID;

...but when this portion is being updated, will need the listId so I can:

this.oListItem = oList.getItemById(listId);

To do so - to assign the correct value to listId - I will need to interrogate the list to see if the "record" for certain values already exists, and thus there already is a listId; pseudocode:

listId = //a "record" with a username value of "<userName>" and a payeeName of "<payeeName>" with a "Completed" value of "false")
if (listId == null) {
      var itemCreateInfo = new SP.ListItemCreationInformation();
      this.oListItem = oList.addItem(itemCreateInfo);
      listId = this.oListItem.ID;

} else {
      this.oListItem = oList.getItemById(listId);
}

My question is: what do I need to replace that pseudocode with? How is a Sharepoint 2010 ListItem interrogated, query-like, to find a matching "record" for specific ListItem member values?

UPDATE

Based on crclayton's first idea, I'm thinking this:

function upsertPostTravelListItemTravelerInfo1() {
  var clientContext = new SP.ClientContext(siteUrl);
  var oList = clientContext.get_web().get_lists().getByTitle('PostTravelFormFields');

  this.website = context.get_web();
  this.currentUser = website.get_currentUser();

  var itemCreateInfo = new SP.ListItemCreationInformation();
  this.oListItem = oList.addItem(itemCreateInfo);

  var travelersEmail = $('traveleremail').val());

  /* If this is an update, the call to getListItemID() will return a val; otherwise (an insert), get from newly instantiated ListItem.  */
  listId = getListItemID(currentUser, travelersEmail);
  if (listId === '') {
    listId = this.oListItem.ID; 
  }

  oListItem.set_item('ptli_formFilledOut', new Date());
  oListItem.set_item('ptli_TravelersName', $('travelername').val());
  oListItem.set_item('ptli_TravelersEmail', travelersEmail);
  . . .
}

function getListItemID(username, payeename) {
  var arrayListEnum = oList.getEnumerator();

  while (arrayListEnum.moveNext()) {
     var listItem = arrayListEnum.get_current();

     if(listItem.get_item("ptli_formPreparedBy") === username &&
        listItem.get_item("ptli_TravelersEmail") === payeename &&
        listItem.get_item("ptli_formCompleted") == false) {

         return listItem.get_id();    
     }
   }
   return '';
}

...might be the ticket.

UPDATE 2

From the answer, I'm getting an err msg on this line:

var arrayListEnum = oList.getEnumerator();

Namely, "Uncaught TypeError: oList.getEnumerator is not a function"

Is is the case that there's no such function named getEnumerator(), or...???

UPDATE 3

I still get, "Uncaught TypeError: oList.getEnumerator is not a function" with this (modified) code:

function getListItemID(username, payeename, oList) {
    var clientContext = new SP.ClientContext.get_current();
    var listItems = oList.getItems("");
    clientContext.load(listItems);
    clientContext.executeQueryAsync(function () {

        var arrayListEnum = oList.getEnumerator();

        while (arrayListEnum.moveNext()) {
            var listItem = arrayListEnum.get_current();

            if (listItem.get_item("userName") === "<userName>" &&
        listItem.get_item("payeeName") === "<payeeName>" &&
        listItem.get_item("Completed") == false) {

                return listItem.get_id();
            }
        }
        return '';
    });
}

I'm calling it this way:

function upsertPostTravelListItemTravelerInfo1() {
    var clientContext = SP.ClientContext.get_current();
    var oList = clientContext.get_web().get_lists().getByTitle('PostTravelFormFields');

    this.website = clientContext.get_web();
    currentUser = website.get_currentUser();

    var itemCreateInfo = new SP.ListItemCreationInformation();
    this.oListItem = oList.addItem(itemCreateInfo);

    var travelersEmail = $('traveleremail').val();

    /* If this is an update, the call to getListItemID() will return a val; otherwise (an insert), get from newly instantiated ListItem.  */
    listId = getListItemID(currentUser, travelersEmail, oList);
    if (listId === '') {
        listId = this.oListItem.ID;
    }

So is getEnumerator() a valid function or not? If yes, what am I doing wrong? If not, what can I use in its stead?


Solution

  • It might not be a query-like as you'd like, but what about something like:

     var clientContext = new SP.ClientContext.get_current();
     var listItems = oList.getItems("");
     clientContext.load(listItems);
     clientContext.executeQueryAsync(function(){
    
         var arrayListEnum = listItems.getEnumerator();
    
         while (arrayListEnum.moveNext()) {
             var listItem = arrayListEnum.get_current();
    
             if(listItem.get_item("userName") === "<userName>" &&
                listItem.get_item("payeeName") === "<payeeName>" &&
                listItem.get_item("Completed") == false) {
    
                    return listItem.get_id();    
             }
         }
     });
    

    Or you can use CAML query like so:

     var query = new SP.CamlQuery();
     query.set_viewXml("<View><Query><Where><Contains><FieldRef Name='userName'/>" +
                        "<Value Type='Text'>userName</Value></Contains></Where></Query>" + 
                        "</View>");
     listItems = oList.getItems(query);
    
     clientContext.load(listItems);
     clientContext.executeQueryAsync(onQuerySucceeded, function(){Alert("not found");});
    
     ...
    
     function onQuerySucceeded() {
        var listEnumerator = listItems.getEnumerator();
        while (listEnumerator.moveNext()) {
            console.log(listEnumerator.get_current().get_id());
        }  
     }