0

I have been trying to use Caml Queries to filter SharePoint lists and return the number of times that a given value is found in the SharePoint list. Here is the part of my code that I've been having issues with:

...
var camlString = "<View><Query><Where><Eq><FieldRef Name='School'/>" + 
        "<Value Type= 'Text'>" + [STRING1] + "</Value></Eq><And><Eq><FieldRef Name='StaffingStatus'/>" + 
        "<Value Type= 'Text'>" + [STRING2] + "</Value></Eq></And></Where></Query></View>";  

try{
    ExecuteOrDelayUntilScriptLoaded(function () {retrieveListItems(camlString); }, "sp.js");

}catch(err){
     alert(err.message);
 } 



 }

 //function to pull specific items from a list using a CamlQuery
 //caml parameter takes in the caml query as a string
function retrieveListItems(caml) {
try{
    var clientContext = new SP.ClientContext(siteUrl);
    var oWeb = clientContext.get_web();
    var oList = oWeb.get_lists().getByTitle('[LIST NAME]');

    var camlQuery = new SP.CamlQuery();

camlQuery.set_viewXml(caml);

this.collListItem = oList.getItems(camlQuery);

clientContext.load(collListItem, 'Include(School, Staffing_x0020_Status)');

 var listItemInfo = '';

var listItemEnumerator = collListItem.getEnumerator();

//More code to iterate through the list and count the total number of records
...

When I run this code, I get the following error message:

The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.

This seems to be triggered by the last line in my code snippet above ("collListItem.getEnumerator();"). When I researched this online, I found that the common solution to this problem was to add "Include([FIELD NAMES])" to my clientContext.load statement. I did this, but I am still receiving the error message.

I don't have this issue when I include clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
in my code before "varlistIemInfo ='';" and include all the code after it in a separate "onQuerySucceeded" function. However, I would rather not use this solution since it executes asynchronously and makes my function difficult to use inside of a loop.

Does anyone know of a way that I could get this to work?

I am using SharePoint 2010.

  • load() doesn't actually load the data, but marks the data as needs to be loaded. executeQueryAsync() actually loads all the data that has been marked as needs to be loaded. – Nit Jan 21 '15 at 14:00
3

This is how JavaScript client object model works. After loading, you need to execute clientContext.executeQueryAsync in order to get results back. However, if you don't like the asynchronous execution and want synchronous execution then you can use callbacks of deferreds. An example using JavaScript callbacks:

$(document).ready(function () {
        //don't exectute any jsom until sp.js file has loaded.        
        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', prepareTables);
    });

function prepareTables() {
    getItemsWithCaml('External User Account Request',
            function (camlItems) {
                var listItemEnumerator = camlItems.getEnumerator();
                while (listItemEnumerator.moveNext()) {
                    var listItem = listItemEnumerator.get_current();
                    console.log(listItem.get_item('Title'));
                } console.log('Completed table prparation.');
            },
            function (sender, args) {
                console.log('An error occured while retrieving list items:' + args.get_message());
            });
}    

function getItemsWithCaml(listTitle, success, error) {
    var clientContext = new SP.ClientContext.get_current();
    var list = clientContext.get_web().get_lists().getByTitle(listTitle);
    var camlQuery = new SP.CamlQuery();
    var camlItems = list.getItems(camlQuery);
    clientContext.load(camlItems);
    clientContext.executeQueryAsync(
            function () {
                success(camlItems);
            },
            error
        );
};

An example using deferreds:

$(document).ready(function () {
        //don't exectute any jsom until sp.js file has loaded.        
        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', prepareTables);
    });    

function prepareTables() {
    getItemsWithCaml('External User Account Request').then(
            function (camlItems) {
                var listItemEnumerator = camlItems.getEnumerator();
                while (listItemEnumerator.moveNext()) {
                    var listItem = listItemEnumerator.get_current();
                    console.log(listItem.get_item('Title'));
                } console.log('Completed table prparation.');
            },
            function (sender, args) {
                console.log('An error occured while retrieving list items:' + args.get_message());
            }
        );   
}    

function getItemsWithCaml(listTitle) {
    //use of $.Deferred in the executeQueryAsync delegate allows the consumer of this method to write 'syncronous like' code
    var deferred = $.Deferred();
    var clientContext = new SP.ClientContext.get_current();
    var list = clientContext.get_web().get_lists().getByTitle(listTitle);
    var camlQuery = new SP.CamlQuery();        
    var items = list.getItems(camlQuery);
    clientContext.load(items);
    clientContext.executeQueryAsync(
        Function.createDelegate(this,
            function () { deferred.resolve(items); }),
        Function.createDelegate(this,
            function (sender, args) { deferred.reject(sender, args); }));

    return deferred.promise();
};

See this for more information: http://www.sharepointnadeem.com/2014/10/sharepoint-using-deferredspromises-or.html

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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