Error trying to update Sharepoint list with javascript - javascript

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));
}

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.

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.

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 SPListItems 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;
}

Related

array[oListItem.id] has values but array[6], array[7] etc. are undefined

I retrieve values from a SharePoint list and put them in an array itemprices.
Using console.log("Price of list item at is:" + itemprices[oListItem.id]); will print out the values of the array, but using console.log("itemprices 5: " + itemprices[5]); tells me that they are undefined:
This is the code I used:
var itemprices = [];
// Gets values from Catalogue list; but they can't be used in the Position list because of different formats
function retrieveListItems() {
var clientContext = new SP.ClientContext.get_current();
catalogueList = clientContext.get_web().get_lists().getByTitle('Catalog');
var camlQuery = new SP.CamlQuery(); // initiate the query object
camlQuery.set_viewXml('<View><Query><Where><In><FieldRef Name=\'ID\'/><Values><Value Type=\'Number\'>5</Value><Value Type=\'Number\'>6</Value><Value Type=\'Number\'>7</Value></Values></In></Where></Query></View>');
itemColl = catalogueList.getItems(camlQuery);
// returns the item collection based on the query
context.load(itemColl);
context.executeQueryAsync(retrieveListItemsSuccess, retrieveListItemsFail);
}
function retrieveListItemsSuccess() {
var listItemEnumerator = itemColl.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
itemprices[oListItem.id] = oListItem.get_item('Preis');
console.log("itemprices 5: " + itemprices[5]);
console.log("itemprices 6: " + itemprices[6]);
console.log("itemprices 7: " + itemprices[7]);
console.log("Price of list item at is:" + itemprices[oListItem.id]);
}
}
// This function is executed if the above call fails
function retrieveListItemsFail(sender, args) {
alert('Failed to get list items. Error:' + args.get_message());
}
I don't know if this is a JavaScript issue or a SharePoint issue. What am I doing wrong?
Firstly, please use the right ClientContext object, in the code snippet above, it should be clientContext rather than context and if you want to populate field values into an array, try to use array.push, here is the modified code snippet for your reference:
<script type="text/javascript">
ExecuteOrDelayUntilScriptLoaded(retrieveListItems, 'sp.js');
var itemprices = [];
// Gets values from Catalogue list; but they can't be used in the Position list because of different formats
function retrieveListItems() {
var clientContext = new SP.ClientContext.get_current();
catalogueList = clientContext.get_web().get_lists().getByTitle('Companies');
var camlQuery = new SP.CamlQuery(); // initiate the query object
camlQuery.set_viewXml('<View><Query><Where><In><FieldRef Name=\'ID\'/><Values><Value Type=\'Number\'>5</Value><Value Type=\'Number\'>6</Value><Value Type=\'Number\'>7</Value></Values></In></Where></Query></View>');
itemColl = catalogueList.getItems(camlQuery);
// returns the item collection based on the query
clientContext.load(itemColl);
clientContext.executeQueryAsync(retrieveListItemsSuccess, retrieveListItemsFail);
}
function retrieveListItemsSuccess() {
var listItemEnumerator = itemColl.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
itemprices.push(oListItem.get_item('Title'));
}
console.log(itemprices);
}
// This function is executed if the above call fails
function retrieveListItemsFail(sender, args) {
alert('Failed to get list items. Error:' + args.get_message());
}
</script>
This is my list data:
This is the array from Console:
You can just use this function:
itemprices.map(itemPrice => console.log(itemPrice))

Return SharePoint List GUID from JavaScript

The following code works to get the a list GUID by Title. What I cannot figure out is how to get the code to return that value so it can be assigned to a variable.
I am fairly new to JavaScript so the nuances trouble me. I understand most of what is going on in the code. I added the alert() in the success function however, I cannot figure out where to put the return statement to get the GUID value back.
var list;
function getListId(listTitle) {
var context = new SP.ClientContext.get_current();
var web = context.get_web();
list = web.get_lists().getByTitle(listTitle);
context.load(list, 'Id');
context.executeQueryAsync(Function.createDelegate(this,success), Function.createDelegate(this,error));
}
function success() {
var listId = list.get_id();
// console.log(listId);
alert(listId);
return listId;
}
function error(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
This is asynchronous, so you can't "return" it in the sense you seem to be talking about. What you would normally do, however, is execute the code you need to execute for handling the listId from within your success function:
var list;
function getListId(listTitle) {
var context = new SP.ClientContext.get_current();
var web = context.get_web();
list = web.get_lists().getByTitle(listTitle);
context.load(list, 'Id');
context.executeQueryAsync(Function.createDelegate(this,success), Function.createDelegate(this,error));
}
function success() {
var listId = list.get_id();
// console.log(listId);
alert(listId);
handleListId(listId);
}
function error(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
function handleListId(listId) {
//DO STUFF WITH YOUR listId HERE...
}

JavaScript to set SharePoint Task Assign To

I am done beating my head against the wall on this. I have tried MS code, Code from here
Set "Assigned To" on SharePoint task using Javascript object model
https://social.msdn.microsoft.com/Forums/SqlServer/en-US/2d9775ad-459c-46bc-989b-5d04d40a2f2f/javascript-how-to-reset-task-list-assigned-to-peoplepicker-field?forum=sharepointdevelopment
https://sharepoint.stackexchange.com/questions/137252/add-task-to-tasks-list-through-javascript-in-sharepoint-2013
https://msdn.microsoft.com/en-us/library/office/jj163201.aspx
and other sites.
I have 100% working code that creates a new task on my sharepoint. The only issue is I simply cannot seem to set the Assigned To field.
Here is what I have...
// Start creating of new Tasks
function createListItem(siteUrl) {
var clientContext = new SP.ClientContext(siteUrl);
var oList = clientContext.get_web().get_lists().getByTitle('Tasks');
var itemCreateInfo = new SP.ListItemCreationInformation();
this.oListItem = oList.addItem(itemCreateInfo);
oListItem.set_item('Title', 'My New Item!');
//oListItem.set_item('AssignedTo', "SID");
oListItem.update();
clientContext.load(oListItem);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceededCreate),
Function.createDelegate(this, this.onQueryFailedCreate)
);
}
function onQuerySucceededCreate() {
alert('Item created: ' + oListItem.get_id());
retrieveListItems(site);
}
function onQueryFailedCreate(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
createListItem(site);
//End Create Task
I rolled everything back to this point that works to simply create the task without the Assigned To. so everything I have tried is listed in the above links. I am totally stumped as at one point it assigned the task but to some random person in the company, not a good thing.
First use the web.ensureUser() function to get a reference to a user object. ensureUser() accepts an alias for a user, such as their login name or email address (other alias fields can be defined in the SharePoint user profile service).
You can then get the id property of the user and use that to set the lookup value of your people picker field.
Below is an example that demonstrates how you could accomplish this:
(function(siteUrl){
var clientContext = new SP.ClientContext(siteUrl);
getUser("contoso/JIMBO", // any valid user alias
assignTask, // function to call on success
alert // function to call on error
);
function getUser(username, onSuccess, onError){
var user = clientContext.get_web().ensureUser(username);
clientContext.load(user);
clientContext.executeQueryAsync(
function(){
onSuccess(user);
},
function(sender, args){ onError(args.get_message()); }
);
}
function assignTask(user){
var oList = clientContext.get_web().get_lists().getByTitle('Tasks');
var itemCreateInfo = new SP.ListItemCreationInformation();
var oListItem = oList.addItem(itemCreateInfo);
oListItem.set_item('Title', 'My New Item!');
var assignedToValue = new SP.FieldUserValue();
assignedToValue.set_lookupId(user.get_id());
oListItem.set_item('AssignedTo',assignedToValue);
oListItem.update();
clientContext.load(oListItem);
clientContext.executeQueryAsync(
function(){
onQuerySucceededCreate(oListItem);
},
function(sender, args){
alert(args.get_message());
}
);
}
function onQuerySucceededCreate(oListItem) {
alert('Item created: ' + oListItem.get_id());
//retrieveListItems(site);
}
})("http://contoso.com"); // site URL

Retrieving LookupValues, Javascript SharePoint 2013, Not Working

I've seen a lot of info on the above question but none of it has answered what I'm looking for, so far. I'm trying to retrieve list items that have a great number of lookup fields. I've had success getting to some of the lookup values but not others and I can't figure out why. Also, it would appear that 'null' items are not accepted in the returned data? If the lookup field does not contain a value, it throws an error? Is this correct? Below is my code. The other issue (the big issue mentioned in my title) is that lookup values where I'm trying to pull in something, other than ID or Title, throws an error: reference not found or initialized. In this instance my lookup field is referencing a calc column returned as a single line of text. So my lookup field is Course1Date/DateRange, where DateRange represents the fieldname of the calc column. Error: "The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested."
function getLookupValues(){
var clientContext = SP.ClientContext.get_current();
var list = clientContext.get_web().get_lists().getByTitle('Lookup');
var caml = new SP.CamlQuery();
caml.set_viewXml('<View><Query><Where><Geq>' +
'<FieldRef Name=\'ID\'/><Value Type=\'Number\'>82</Value>' +
'</Geq></Where></Query><RowLimit>10</RowLimit></View>');
var returnedItems = list.getItems(caml);
clientContext.load(returnedItems);
clientContext.executeQueryAsync(success, failure);
}
function success(){
var listiteminfo='';
var enumerator = returnedItems.getEnumerator();
while(enumerator.moveNext())
{
var listItem = enumerator.get_current();
if(listItem.get_item('Course1')) {
var course1 = listItem.get_item('Course1').get_lookupValue();
}
if(listItem.get_item('Course2')) {
var course2 = listItem.get_item('Course2').get_lookupValue();
}
if(listItem.get_item('Course1Date')) {
var course1Date = listItem.get_item('Course1Date').get_lookupValue();
} //throws error for this lookup field
listiteminfo += '\nCourse1: '+course1+'\nCourse2: '+course2+'\nCourse1Date: '+course1Date;
}
alert(listiteminfo);
}
function failure(){
alert("Failed");
}
You have initialize the fields to get Lookup Values. Have to load the ListItem in context. And if there is a null value in lookup field, get.lookupValue() will throw an exception. So check the field value is not null before getting lookup value. Please try my workaround below and let me know if it works.
function getLookupValues() {
var clientContext = SP.ClientContext.get_current();
var list = clientContext.get_web().get_lists().getByTitle('Lookup');
targetListItem = list.getItemById(82);
clientContext.load(targetListItem, 'Title');
clientContext.load(targetListItem, 'Course1');
clientContext.load(targetListItem, 'Course1Date');
clientContext.load(targetListItem, 'Course2');
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded() {
var resultData = "";
resultData += targetListItem.get_item('Title');
if (targetListItem.get_item('Course1') != null)
resultData += targetListItem.get_item('Course1').get_lookupValue();
if (targetListItem.get_item('Course1Date') != null)
resultData += targetListItem.get_item('Course1Date').get_lookupValue();
if (targetListItem.get_item('Course2') != null)
resultData += targetListItem.get_item('Course2').get_lookupValue();
alert(resultData);
}
function onQueryFailed(sender, args) {
alert('Request failed. \nError: ' + args.get_message() + '\nStackTrace: ' + args.get_stackTrace());
}

returning values from an async delegate function

I am working with the Sharepoint Client Object Model using javascript and looking to make as much of my code as reusable as possible.
Examples of using the COM usually looks like this with a call and then a success delegate function to output the results.
function loadProfile()
{
var context = SP.ClientContext.get_current();
var web = context.get_web();
var userInfoList = web.get_siteUserInfoList();
camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('');
this.listItems = userInfoList.getItems(camlQuery);
context.load(listItems);
context.executeQueryAsync(Function.createDelegate(this, this.onProfileSuccessMethod), Function.createDelegate(this, this.onFail));
}
function onProfileSuccessMethod(sender, args)
{
var item = listItems.itemAt(0);
var first_name = item.get_item('FirstName');
var last_name = item.get_item('LastName');
alert(first_name + " " + last_name);
}
function onFail(sender, args)
{
alert('Error: ' + args.get_message() + '\n' + args.get_stackTrace());
}
What I am trying to achieve is being able return the values after instantiating an object but given that it is asynchronous I am not sure how this is possible, would I need to "listen" for the call to complete before values are returned.
Would it be something like this? Or can you not have a delegate function internal to the function it creates it from. Apologies for my limited understanding!
var profile = new loadProfile("testid");
alert(profile.onProfileSuccessMethod());
function loadProfile (id)
{
this.user_id = id;
var context = SP.ClientContext.get_current();
var web = context.get_web();
var userInfoList = web.get_siteUserInfoList();
camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('');
this.listItems = userInfoList.getItems(camlQuery);
context.load(listItems);
context.executeQueryAsync(Function.createDelegate(this, this.onProfileSuccessMethod), Function.createDelegate(this, this.onFail));
this.onProfileSuccessMethod = function()
{
var item = listItems.itemAt(0);
this.first_name = item.get_item('FirstName');
this.last_name = item.get_item('LastName');
return this.first_name
};
}
If it is asynchronous, it is impossible to return values from it. You need to use a callback pattern.
function secondStep(data){
console.log(data)
}
var profile = new loadProfile("testid", secondStep);
and
function loadProfile (id, callback)
...
this.onProfileSuccessMethod = function(){
callback({});
}

Categories

Resources