0

I am using a JavaScript button to set a Field-2 on each selected list item from "false" to "true". It first checks if Field-1 is empty, and if it is, sets Field-2 to true. The relevant code is as follows:

function ApproveAllSelected() {
this.context = SP.ClientContext.get_current();
var selectedItems = SP.ListOperation.Selection.getSelectedItems(context);
var list = context.get_web().get_lists().getByTitle("List Title Here");
this.items = [];
var item;
for (item in selectedItems) {
var approvalItem = list.getItemById(selectedItems[item].id);
items.push(approvalItem);
context.load(approvalItem, "Field1", "Field2");
}
context.executeQueryAsync(Function.createDelegate(this, this.OnSuccess), OnFailed);
window.location = document.location;
window.location.href = window.location;
}

function OnSuccess(sender, args) {
for (var j = 0; j < this.items.length; j++) {
    var value = this.items[j].get_item("Field2");
    if (value == null)
        {
        this.items[j].set_item("Field1", 1);
        this.items[j].update();
        this.context.executeQueryAsync();
        }
    }
}

The strange thing is, this code is successful, but seems to only be successful on 4-5 list items at once. If I select 20 list items and then hit the button, only 4-5 have Field-2 set successfully, and the other list items act as if nothing happened. Other times, nothing in the list changes. I am refreshing the list between tries as well.

There are no errors thrown from either On-failed or in my SharePoint ULS logs. I see no JavaScript errors on the page in my browser debugger, either.

If I continuously re-select the items and press the approval button over and over, the items will eventually all be marked as "true".

3
  • 1
    First off, you should not use the for..in looping construct to iterate collections in JavaScript. It does not do what you think it does. Use a plain old for loop instead. Commented Jun 11, 2014 at 15:52
  • Thank you for your input. I do not have much experience with Javascript and I guess it shows here. It looks like for...in has a very specific use. I will switch it to a regular for loop. Commented Jun 11, 2014 at 22:55
  • 1
    @DerekGusoff I had the same thought, but the SP.ListOperation.Selection.getSelectedItems(context); actually returns a map so that is actually the appropriate way to iterate the items. Commented Jun 13, 2014 at 20:33

2 Answers 2

1

In the OnSuccess function, the final call to executequeryasync should be after the for loop.

Otherwise your code seems okay, this might also be a logic issue. Why do you check if your value == null? can it be undefined? You can use if(value) instead.

if(!value){ //code here }
2
  • I will try swapping the positioning of the executeQueryAsync tomorrow. The if statement check is actually for a different field. I am conditionally setting field 1 to true if field 2 is blank. Commented Jun 11, 2014 at 22:57
  • This actually solved the issue. It seems that running multiple "executequeryasync" so quickly caused issues on the server side and locked things up. Thanks, I appreciate the help. Commented Jun 12, 2014 at 14:24
1

Have you tried giving out the for-loop index? often there's the problem that the loop continues while your editing hasn't completed and then the next update is with a index a few higher than what you would think it should be.

That's because javascript is working async and not waiting for anything to finish until the loop goes into the next step.

2
  • I will try printing out the index and make sure it hits everything--I am assuming this is what you mean. Commented Jun 11, 2014 at 22:58
  • yes this is what I mean, if every update is really executed and not only some of them. Commented Jun 12, 2014 at 6:09

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.