Reputation: 57
Update
I have now tried a new approach. This works when I call it one time but the second time it tells me that the collection hasnt been initiated for some reason. The comments in the test function of this code snippet will clarify my problem.
Javascript:
function test(){
//this first call works
countRetrieve('Very', 'Difficult');
//this second call generates error that collListItem hasnt been initiated
countRetrieve('Less', 'Interesting');
}
function countRetrieve(grade, title) {
var siteUrl = '/sites/MySite';
var clientContext = new SP.ClientContext(siteUrl);
var oList = clientContext.get_web().get_lists().getByTitle('Summary');
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View><Query><Where>' +
'<And>' +
'<Eq><FieldRef Name=\'Grad\'/><Value Type=\'Text\'>' +
grade +
'</Value></Eq>' +
'<Eq><FieldRef Name=\'Title\'/><Value Type=\'Text\'>' +
title +
'</Value></Eq>' +
'</And>' +
'</Where></Query></View>');
this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onRetrieveQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onRetrieveQuerySucceeded(sender, args) {
listItemEnumerator = collListItem.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
itemId = oListItem.get_id();
itemCount = oListItem.get_item('Count');
}
updateCount();
}
function updateCount() {
var clientContext = new SP.ClientContext('/sites/MySite');
var oList = clientContext.get_web().get_lists().getByTitle('Summary');
this.oListItem = oList.getItemById(itemId);
//update the count, raise it by one
var c = itemCount + 1;
oListItem.set_item('Count', c);
oListItem.update();
clientContext.executeQueryAsync(Function.createDelegate(this, this.onUpdateSucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onUpdateSucceeded(sender, args){
alert('item count updated');
}
Im trying to retrieve the current value of the column "Count" in my list, and then rise this value by 1. However i get an error that tells me the Collection has not been initialized.
Didnt it get initialized in this.collListItem = oList.getItems(camlQuery); ?
It is possible this function is totally wrong, Im very grateful for tips on how to perform this task as Im new both to Sharepoint and Javascript.
This is my code (javascript):
function countUpdate() {
var siteUrl = '/sites/MySite';
var clientContext = new SP.ClientContext(siteUrl);
var oList = clientContext.get_web().get_lists().getByTitle('Summary');
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View><Query><Where>' +
'<And>' +
'<Eq><FieldRef Name=\'Grade\'/><Value Type=\'Text\'>' +
'Really' +
'</Value></Eq>' +
'<Eq><FieldRef Name=\'Property\'/><Value Type=\'Text\'>' +
'Narrow' +
'</Value></Eq>' +
'</And>' +
'</Where></Query></View>');
this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onUpdateQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
//update
var listItemEnumerator = collListItem.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
var count = oListItem.get_item('Count');
oListItem.set_item('Count', '40');
oListItem.update();
}
clientContext.executeQueryAsync(Function.createDelegate(this, this.onUpdateQuerySucceeded),Function.createDelegate(this, this.onQueryFailed));
}
Upvotes: 0
Views: 4837
Reputation: 1
Thanks for answer Jim. Not only question owner finds your post useful.
To easien things up i'm posting a sample:
This code can update multiple SPListItem
s by clicking on one CheckBox
var appOpsUrl = '/sites/AppOpsRep';
var coll;
function UpdateTargetInReport(checkBox, refValueOne, refValueTwo)
{
var clientContext = new SP.ClientContext.get_current();
var list = clientContext.get_web().get_lists().getByTitle('SLA Fulfillment');
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View><Query><Where><And><Eq><FieldRef Name=\'Application\' /><Value Type=\'Text\'>' + refValueOne + '</Value></Eq><Eq><FieldRef Name=\'Metric_x0020_name\' /><Value Type=\'Text\'>' + refValueTwo + '</Value></Eq></And></Where></Query></View>');
coll = list.getItems(camlQuery);
clientContext.load(coll);
clientContext.executeQueryAsync(Function.createDelegate(this, function(){ UpdateTargetInReport_onQuerySucceeded(refValueTwo, checkBox); }), Function.createDelegate(this, function(sender,args) { UpdateTargetInReport_onQueryFailed(sender, args, checkBox); }));
}
function UpdateTargetInReport_onQuerySucceeded(refValueTwo, checkBox)
{
var clientContext = new SP.ClientContext.get_current();
var listItemEnumerator = coll.getEnumerator();
while(listItemEnumerator.moveNext())
{
var listItem = listItemEnumerator.get_current();
listItem.set_item('In_x0020_Report', checkBox.checked);
listItem.update();
}
clientContext.executeQueryAsync(Function.createDelegate(this, function() { UpdateTargetInReport_onUpdateQuerySucceeded(refValueTwo); }), Function.createDelegate(this, function(sender,args) { UpdateTargetInReport_onUpdateQueryFailed(sender, args, checkBox); } ));
}
function UpdateTargetInReport_onQueryFailed(sender, args, checkBox)
{
SP.UI.Notify.addNotification('Request failed. ' + args.get_message());
checkBox.checked = !checkBox.checked;
}
function UpdateTargetInReport_onUpdateQuerySucceeded(refValueTwo)
{
SP.UI.Notify.addNotification(refValueTwo + ' updated successfully');
}
function UpdateTargetInReport_onUpdateQueryFailed(sender, args, checkBox)
{
SP.UI.Notify.addNotification('Request failed. ' + args.get_message());
checkBox.checked = !checkBox.checked;
}
Upvotes: 0
Reputation: 1230
As answered your problem lies in the asynchronous nature of AJAX. Your call is made and other code IMMEDIATELY continues BEFORE it's returned. So what you need is a "handler" - a function to call when your request is complete that will handle the data returned by it.
executeQueryAsync takes as it's first parameter a method (a function) "succeededCallback" - you need to create that method and give it to this call (with no parens - you want to pass a reference to the function, not run it). That method will be automatically called when the request completes and, again automatically, include the results of the call as the first argument.
Looking at your code and being as simplistic as possible you're going to have to chain together three functions:
1) Sets up the initial call and when done calls 2).
2) Accepts the results from the initial call, acts upon them, sets up the second call and when done calls 3)
3) Accepts the results from the second call, acts upon them.
You can use the built in the SP functions but honestly I find them a little cumbersome. I built my own AJAX abstrction to do this here:
http://depressedpress.com/javascript-extensions/dp_ajax/
The implementation is a bit different but the ideas are exactly the same - perhaps looking through some of the examples there might bring things into clearer focus.
Hope this helps. For the little that it's worth you're in good company: this is one of those "nobody ever gets it until they really get it" things that seems to be a stumbling block for pretty anybody the first time.
Upvotes: 1
Reputation: 100547
You need to continue execution in onUpdateQuerySucceeded function - before that list will not have any information as request need to be send to server and response hamdled before you get items.
The functions are called XXXXAsync exactly for this reason - calling it does not give result immediatelly, but rater asynchronously in success callback.
Upvotes: 0