2

This is an issue I've been struggling with - What I am doing is using a script editor web part and when a user clicks the button, I check to see if a list exists inside of a loop (in this example, it could be called Data1 - Data10) and if so, then I want to pull all of the items from that list based on the query, which is based on filters with other controls (Ignore the datepickers/filters - I know the query works)

The problem I'm hitting is that I'm running these async calls inside of my 'does the list exist' loop and getting to the getEnumerator line where I receive the error :

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

I had previously posted a simplified version of this question and didn't receive a response so was hoping if I posted the entirety of my solution that it may give me an answer.

Thanks

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js "></script>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
    <script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
    <script type="text/javascript" language="javascript">

    $(function() {
        $( "#datepickerStart" ).datepicker();
        $( "#datepickerEnd" ).datepicker();
    });

    var valStopped = 10;
    var allItems;
    function getListData() 
    {
        var _clientContext;
        var _web;
        _clientContext = new SP.ClientContext.get_current();
        _web = _clientContext.get_web();
        var lists = _web.get_lists();
        _clientContext.load(lists,'Include(Title)');
        //Get all lists...
        var listTitle = "";
        var arrayOfMatchedLists = [];
        var responses = {exists:false,record:0};
        var arrayOfPromises = [];

        for (var j = 1; j < valStopped; j++) //loop through all potential lists and see if they exist
        {
            listTitle = "Data" + j;
            arrayOfPromises.push(get_isListExists(listTitle,j,function(listExists,counter){
            if (listExists){
                responses = {exists:listExists,record:counter};
                arrayOfMatchedLists.push(responses);
            }
            },function(sender,args){}));
        }
        $.when.apply($, arrayOfPromises).done(function() {
        var largest = 0;
        for (var item in arrayOfMatchedLists) 
        {
        //Get the largest list index
            if (arrayOfMatchedLists[item].record > largest)
            {
                largest = arrayOfMatchedLists[item].record;
            }
        }
        populateList(largest);
            }); 
    }


    function populateList(counter) 
    {

    for (var i = 1; i <= counter; i++)
        {

            var _clientContext;
            var _web;
            _clientContext = new SP.ClientContext.get_current();
            _web = _clientContext.get_web();
            var listTitle = "Data" + i; //+ i;
            var list = _web.get_lists().getByTitle(listTitle);
            var myquery = new SP.CamlQuery();
            if ($("Data6").val() !== "All") //get Data6 as a filter if it's not all, else don't use Data6 as a filter.
            {
                myquery.set_viewXml('<View><ViewFields><FieldRef Name=\'Data1\'/><FieldRef Name=\'Data2\'/><FieldRef Name=\'Data3\'/><FieldRef Name=\'Data4\'/><FieldRef Name=\'Data5\'/><FieldRef Name=\'Data6\'/><FieldRef Name=\'Data7\'/><FieldRef Name=\'Data8\'/><FieldRef Name=\'Data9\'/><FieldRef Name=\'Data10\'/></ViewFields></View>');
            }
            //else set query as all facilities
            allItems = list.getItems(myquery); 
            _clientContext.load(allItems, 'Include(Data1,Data2,Data3,Data4,Data5,Data6,Data7,Data8,Data9,Data10)');
            _clientContext.executeQuery(Function.createDelegate(this, this.onQuerySucceeded()), Function.createDelegate(this, this.onQueryFailed));
        }           
    }

    function onQuerySucceeded() 
    {
        var Data1 = null;
        var Data2 = null;
        var Data3 = null;
        var Data4 = null;
        var Data5 = null;
        var Data6 = null;
        var Data7 = null;
        var Data8 = null;
        var Data9 = null;
        var Data10 = null;
        var txtHTML = "";

        console.log("before enum");
        var listEnumerator = allItems.getEnumerator();
        console.log("get enumerator");
            while (listEnumerator.moveNext()) {
                    console.log("before got current");
                    var currentItem = listEnumerator.get_current();
                    console.log("got current");
                    Data1 = currentItem.get_item('Data1');
                    Data2 = currentItem.get_item('Data2');
                    Data3 = currentItem.get_item('Data3');
                    Data4 = currentItem.get_item('Data4');
                    Data5 = currentItem.get_item('Data5');
                    Data6 = currentItem.get_item('Data6');
                    Data7 = currentItem.get_item('Data7');
                    Data8 = currentItem.get_item('Data8');
                    Data9 = currentItem.get_item('Data9');
                    Data10 = currentItem.get_item('Data10');
                    var row = document.createElement("tr");

                    txtHTML = txtHTML + "<tr>";
                    txtHTML = txtHTML + "<td>";
                    if (Data1 != null) {
                        txtHTML = txtHTML + "<p>" + Data1 + "</p>";
                    }
                    txtHTML = txtHTML + "</td>";

                    txtHTML = txtHTML + "<td>";
                    if (Data2 != null) {
                        txtHTML = txtHTML + "<p>" + Data2 + "</p>";
                    }
                    txtHTML = txtHTML + "</td>";

                    txtHTML = txtHTML + "<td>";
                    if (Data3 != null) {
                        txtHTML = txtHTML + "<p>" + Data3 + "</p>";
                    }
                    txtHTML = txtHTML + "</td>";

                    txtHTML = txtHTML + "<td>";
                    if (Data4 != null) {
                        txtHTML = txtHTML + "<p>" + Data4 + "</p>";
                    }
                    txtHTML = txtHTML + "</td>";                                

                    txtHTML = txtHTML + "<td>";
                    if (Data5 != null) {
                        txtHTML = txtHTML + "<p>" + Data5 + "</p>";
                    }
                    txtHTML = txtHTML + "<td>";
                    if (Data6 != null) {
                        txtHTML = txtHTML + "<p>" + Data6 + "</p>";
                    }
                    txtHTML = txtHTML + "</td>";    
                    txtHTML = txtHTML + "<td>";
                    if (Data7 != null) {
                        txtHTML = txtHTML + "<p>" + Data7 + "</p>";
                    }
                    txtHTML = txtHTML + "</td>";    
                    txtHTML = txtHTML + "<td>";
                    if (Data8 != null) {
                        txtHTML = txtHTML + "<p>" + Data8 + "</p>";
                    }
                    txtHTML = txtHTML + "</td>";    
                    txtHTML = txtHTML + "<td>";
                    if (Data9 != null) {
                        txtHTML = txtHTML + "<p>" + Data9 + "</p>";
                    }
                    txtHTML = txtHTML + "</td>";    
                    txtHTML = txtHTML + "<td>";
                    if (Data10 != null) {
                        txtHTML = txtHTML + "<p>" + Data10 + "</p>";
                    }
                    txtHTML = txtHTML + "</td>";    
                    txtHTML = txtHTML + "</tr>";
            }
            console.log("ran");
        $("#tblCustomListData").append(txtHTML);
    }

    function onQueryFailed(sender, args) 
    {
        alert("failed Message" + args.get_message());
    }

    function get_isListExists(listTitle, counter, OnSuccess, OnError){

        var ctx = SP.ClientContext.get_current();
        var web = ctx.get_web();
        var lists = web.get_lists();
        ctx.load(lists); 
        var outValue = $.Deferred();
        ctx.executeQueryAsync(
          function() {
          if (counter <= valStopped){
            var listExists = false;  
            var le = lists.getEnumerator();
            while (le.moveNext()) {
                    var list = le.get_current();
                    if(list.get_title() == listTitle) {
                        listExists = true;
                        break;
                    }
                }
                }

          outValue.resolve();
          OnSuccess(listExists,counter);
          OnError();    
        });
        return outValue.promise();
    }

</script>


     <p> Data6: <select id="Data6">
      <option value="Op1">Op1</option>
      <option value="Op2">Op2</option>
      <option value="Op3">Op3</option>
      <option value="Op4">Op4</option>
      <option value="Op5">Op5</option>
      <option value="Op6">Op6</option>
    </select> </p>
    <p>Start Date: <input type="text" id="datepickerStart">
    End Date: <input type="text" id="datepickerEnd"></p>
    <center><button ID="retrieveList" onclick="ExecuteOrDelayUntilScriptLoaded(getListData(), 'sp.js');return false">Retrieve List</button></center></br>
    <table id="tblCustomListData" border="1">
        <thead>
            <tr>
                <th>Data1
                </th>
                <th>Data2
                </th>
                <th>Data3
                </th>
                <th>Data4
                </th>
                <th>Data5
                </th>
                <th>Data6
                </th>
                <th>Data7
                </th>
                <th>Data8
                </th>
                <th>Data9
                </th>
                <th>Data10
                </th>                       
            </tr>
        </thead>
    </table>

2 Answers 2

0

Use deferred/promises or JavaScript callbacks to get data synchronously. I will try to explain with an example. The code below will throw error:

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.

<script type="text/javascript">
$(document).ready(function () {
        //don't exectute any jsom until sp.js file has loaded.        
        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', prepareTables);
    });

var camlItems;
function prepareTables() {
        var clientContext = new SP.ClientContext.get_current();
        var list = clientContext.get_web().get_lists().getByTitle('External User Account Request');
        var camlQuery = new SP.CamlQuery();
        for (var i = 0; i < 3; i++) {                        
            camlItems = list.getItems(camlQuery);
            clientContext.load(camlItems);
            clientContext.executeQueryAsync(
                Function.createDelegate(this, this.onQuerySucceeded),
                Function.createDelegate(this, this.onQueryFailed)
            );
        }
    }    

    function onQuerySucceeded(sender, args) {
        var listItemEnumerator = camlItems.getEnumerator();
        while (listItemEnumerator.moveNext()) {
            var listItem = listItemEnumerator.get_current();
            console.log(listItem.get_item('Title'));
        }
    }

    function onQueryFailed(sender, args) {
        console.log('An error occured while retrieving list items:' + args.get_message());
    }

   </script>

However, the same code can be rewritten using deffered/promises and it will work properly:

<script type="text/javascript">
    $(document).ready(function () {
        //don't exectute any jsom until sp.js file has loaded.        
        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', prepareTables);
    });

    function prepareTables() {
        for (var i = 0; i < 3; i++) {
            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'));
                    }
                },
                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();
    };

   </script>

See more here.

0

You also have the option to pull in All the lists in the site the get_lists() function, iterating through these lists and checking aggainst the array

--psuedo code

Call context load site lists enumerate through those site lists and load title into array load array into session

Then check, inside of while or for method, Is list title in array If yes - do something If no - do something else

looking at it this way is much simpler and much less overhead, especially when debuggin

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.