0

I am using Javascript to create a CAML Query to get data from a list in Sharepoint 2013. It works perfectly. Instead of pushing it to HTML, I need to push the output to a variable as a string for use in another function. My issue is, the output shows in the console from the call within the code, but the variable is empty outside of the code, even though my variable is global. What am I missing?

var optionInfo = '';

    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', GetProps);

    function GetProps() {
    var hclientContext = new SP.ClientContext('http://mysite');
    var hList = hclientContext.get_web().get_lists().getByTitle('mylist');
    // New caml for getting list based on view
    var camlQueryHR = new SP.CamlQuery();
    camlQueryHR.set_viewXml('<View Scope="RecursiveAll"><Query>'  +
    '<OrderBy><FieldRef Name="Title" Ascending="True" /></OrderBy>' +
    '</Query><RowLimit>500</RowLimit><ViewFields>' +
    '<FieldRef Name="Sub_x0020_Type" /><FieldRef Name="Title" /></ViewFields><QueryOptions>' +
    '<ViewAttributes Scope="Recursive" /></QueryOptions></View>');
    this.hcollListItem = hList.getItems(camlQueryHR);
    // end of caml for list view
    //this.ncollListItem = nList.getItems("");
    hclientContext.load(hcollListItem);
    hclientContext.executeQueryAsync(
    Function.createDelegate(this, this.onQuerySucceeded),
    Function.createDelegate(this, this.onQueryFailed)
    );
    }

    function onQuerySucceeded(sender, args) {
    var hlistItemEnum = hcollListItem.getEnumerator();

    while (hlistItemEnum.moveNext()) {
        var hListItem = hlistItemEnum.get_current();
        var propName = hListItem.get_item('Title');
        optionInfo += '<option value="' + propName + '">' + propName + '</option>';
         }

    console.log("Output within CAML:" + optionInfo); //Appears as expected
    //$('.locations').append(optionInfo);

    }

    function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
    }

    console.log("Output outside of CAML:" + optionInfo); //shows as an empty string
0

This is an async timing issue.

The reason your "outside of CAML" console log shows the variable as being an empty string is because at the time that line of code executes, your onQuerySucceeded callback function has not fired yet, so it hasn't populated the variable yet.

In fact as I look at the code, I see that that console log line is outside of all the functions, so it is probably trying to log that variable value even before SP.CLientContext is loaded and before GetProps() gets called.

If you give yourself a test button that triggers a simple function that will log the value of that variable, and you wait until you see the "output within CAML" log statement with the correct variable value, and then click your test button, you will see the correct variable value.

Another way to see what's going on would be to add some extra log entries, like this:

console.log('setting optionInfo to empty string');
var optionInfo = '';

console.log('telling SP.SOD to load SP.ClientContext before executing GetProps');
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', GetProps);

function GetProps() {

    console.log('GetProps started');

    var hclientContext = new SP.ClientContext('http://mysite');
    var hList = hclientContext.get_web().get_lists().getByTitle('mylist');
    // New caml for getting list based on view
    var camlQueryHR = new SP.CamlQuery();
    camlQueryHR.set_viewXml('<View Scope="RecursiveAll"><Query>' +
        '<OrderBy><FieldRef Name="Title" Ascending="True" /></OrderBy>' +
        '</Query><RowLimit>500</RowLimit><ViewFields>' +
        '<FieldRef Name="Sub_x0020_Type" /><FieldRef Name="Title" /></ViewFields><QueryOptions>' +
        '<ViewAttributes Scope="Recursive" /></QueryOptions></View>');
    this.hcollListItem = hList.getItems(camlQueryHR);
    // end of caml for list view
    //this.ncollListItem = nList.getItems("");
    hclientContext.load(hcollListItem);

    console.log('GetProps about to send async request to SharePoint');
    hclientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded),
        Function.createDelegate(this, this.onQueryFailed)
    );

    console.log('GetProps ended');
}

function onQuerySucceeded(sender, args) {

    console.log('onQuerySucceeded started')

    var hlistItemEnum = hcollListItem.getEnumerator();

    while (hlistItemEnum.moveNext()) {
        var hListItem = hlistItemEnum.get_current();
        var propName = hListItem.get_item('Title');
        optionInfo += '<option value="' + propName + '">' + propName + '</option>';
    }

    console.log("Output within CAML:" + optionInfo); //Appears as expected
    //$('.locations').append(optionInfo);

    console.log('onQuerySucceeded ended');
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

console.log("Output outside of CAML:" + optionInfo); //shows as an empty string

That should output:

setting optionInfo to empty string
telling SP.SOD to load SP.ClientContext before executing GetProps
Output outside of CAML:
GetProps started
GetProps about to send async request to SharePoint
GetProps ended
onQuerySucceeded started
Output within CAML: // with correct variable value
onQuerySucceeded ended

Also, as a side note, the CAML query itself is that XML string you are passing to the set_viewXml() function, so it is a bit of a misnomer to say "within CAML" and "outside of CAML". If you were really "within CAML", you would be in the middle of that XML string somewhere.

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