I am trying to get a list named 'Tasks' that is contained within every Subsite in the WebCollection.
I successfully execute the AsyncQuery for the WebCollection with this function:
function getProjectSites() {
clientContext = new SP.ClientContext.get_current();
if (clientContext != undefined && clientContext != null) {
var web = clientContext.get_web();
this.webCollection = web.getSubwebsForCurrentUser(null);
clientContext.load(this.webCollection);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), null);
}
}
From here I am able to iterate through every Subsite and get their Title and their Relative Server Url with the following:
function onQuerySucceeded() {
var webEnumerator = this.webCollection.getEnumerator();
while (webEnumerator.moveNext()) {
var subWeb = webEnumerator.get_current();
console.log('Site: ' + subWeb.get_title() + ' URL: ' + subWeb.get_serverRelativeUrl());
}
}
From this point is where I start getting errors, if I attempt to get the list 'tasks' and modify my function slightly to this:
function onQuerySucceeded() {
var webEnumerator = this.webCollection.getEnumerator();
while (webEnumerator.moveNext()) {
var subWeb = webEnumerator.get_current();
var listCollection = subWeb.get_lists();
taskList = listCollection.getByTitle('Tasks');
clientContext.load(taskList);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onSubQuerySucceeded), null);
console.log('Site: ' + subWeb.get_title() + ' URL: ' + subWeb.get_serverRelativeUrl());
}
}
It passes the each Tasks list into the SubQuery Function fine, if the contents of the SubQuery are as follows:
function onSubQuerySucceeded(){
console.log(taskList);
}
The output in Firebug is this, repeated for how many Subsites there are.
Object { $0_0: Object, $2_0: Object } indexTest.aspx:691:3
But as soon as I attempt to get any variable from the Object for example with
function onSubQuerySucceeded(){
console.log(taskList.get_title());
}
I start getting this error repeatedly, but not consistently.
Error: The property or field 'Title' has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
But the last item will print the actual Title of the list which is 'Tasks'. Any ideas? It seems odd that get_title will work for at least one of the Objects every time.
Update:
As per your suggestion, I have switched to the bind() method, strange that Microsoft use createDelegate() in the MSDN. And on your comment with my use of 'this.' Since ES5 when this is explicitly stated it doesn't send the global object any more, just what was declared for the function, so I'm structuring my parameter passing around that. You mention combining my query for the webcollection as well as the subweb's camlquery, is it ok to iterate through the webcollection before loading it into context?
Here's how I've restructured it so far:
function getProjectSites() {
clientContext = new SP.ClientContext.get_current();
if (clientContext != undefined && clientContext != null) {
var web = clientContext.get_web();
this.webCollection = web.getSubwebsForCurrentUser(null);
clientContext.load(this.webCollection);
clientContext.executeQueryAsync(onQuerySucceeded.bind(this), null);
}
}
function onQuerySucceeded() {
tableOfContentsHtml = '<h2>Project Site Index</h2>';
var webEnumerator = this.webCollection.getEnumerator();
while (webEnumerator.moveNext()) {
var subWeb = webEnumerator.get_current();
var listCollection = subWeb.get_lists();
var taskList = listCollection.getByTitle('Tasks');
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('' +
'<View>'+
'<ViewFields>'+
'<Query>'+
'<OrderBy>'+
'<FieldRef Name="DueDate"/>'+
'</OrderBy>'+
'</Query>'+
'</ViewFields>'+
'</View>');
this.colListItems = taskList.getItems(camlQuery);
clientContext.load(colListItems);
clientContext.executeQueryAsync(onSubQuerySucceeded.bind(this), onSubQueryFailed.bind(this));
}
}
function onSubQuerySucceeded(){
//var listEnumerator = this.colListItems.getEnumerator();
console.log(this.colListItems.get_count());
}
This code will produce the real individual item count for each list for each individual subsite. But attempting to even enumerate them, the commented out line in SubQuerySucceeded() it throws the same error as before. Is this to do with the Scope still? The only variable I'm using globally is the context between the two Query functions.
createDelegate
in all blogs because it is IE8 code, and (we all) never updates blogs or tech articles. Instead of JSOM, REST calls are easier.. a bit more work but less chance of running into Scope and Context issues.