1

I'm trying to retrieve all the selected items and then get the value in the field name E_x002d_Mail_x0020_1. However there seem to be an issue regarding looping the ctx.executeQueryAsync, since it returns the same row data instead of the different ones and sometimes it returns following error:

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

What am i doing wrong in order to return all the selected items in in this field E_x002d_Mail_x0020_1?

i've tried to debug by checking whether selectedItemId returns the different id's and it does so it gotta be something with the function loop and the ctx?

<button type="button" id="getlistitemid" value="Get Selected Items ID" onclick="GetSelectedItemsID()" />

<script type="text/javascript">
function GetSelectedItemsID() {

SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function(){

var listGuid = SP.ListOperation.Selection.getSelectedList();
//in this example only first selected item is retrieved

    var allSelectedItems = SP.ListOperation.Selection.getSelectedItems();
    var item;
    var ItemEmails='mailto:';


    for (item in allSelectedItems){

        var selectedItemId = allSelectedItems[item].id;
        var ctx = SP.ClientContext.get_current();
        var web = ctx.get_web();
        var lists = web.get_lists();
        var list = lists.getById(listGuid);
        var item = list.getItemById(selectedItemId);
        ctx.load(item);

        ctx.executeQueryAsync(function() {
        var title = item.get_item("E_x002d_Mail_x0020_1");
        console.log(title);
        ItemEmails += title + ";";

        }, function(){alert("error");

        });


    }

    window.location.href = ItemEmails;

});
}


</script>
  • are you sure about the exact field name. use caml builder to get the internal name – kesava Aug 5 '15 at 20:44
  • i'm sure if i do not use loop and just write 0 ìnstead of item in var selectedItemId = allSelectedItems[item].id it returns the correct from that field – frederik Aug 5 '15 at 20:48
  • You seem to create two variables with same name item. Try giving the second one different name. – Nadeem Yousuf Aug 5 '15 at 20:55
  • That seem to be one issue, which i now have fixed, but i till sometimes get Uncaught 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 and when i dont it just return the same field values even though i selected two different items. – frederik Aug 5 '15 at 21:01
4

There are some JavaScript errors here

  1. variable declarations - javascript has variable scopes - but they are only at the function() { } level. So in your initial code, var item (line 2) and var item = list.getItemById(selectedItemId); are clobbering the same variable. This as Nadeem pointed out makes your for 'loop' unpredictable.

This is NOT the same as C/C# - where variable scopes at any block (brackets) { level }

  1. for syntax on objects. JavaScript's for syntax should not be used in the way you use foreach in C#. for (item in allSelectedItems) iterates item through every member of the allSelectedItems object, including not just the indexes allSelectedItems[0], allSelectedItems[1] etc but also other member properties like allSelectedItems.length

If you are looping through an array, use the array syntax:

// allSelectedItems = [1,2,3]

for(var i = 0; i < allSelectedItems.length; i++) {
  item = allSelectedItems[i];
}

If you are looping through members of an object, mapping or associative array

// obj = { a: 1, b: 2, c: 3 }
for(var key in obj) {
    var prop = obj[key];
}
  1. The redirect window.location.href is happening before the async call has returned - this means you will almost never have data ready before the call.

  2. The clientContext can execute all the queries in one hit, so it is safe to move it outside of the loop and just execute once.

Try structuring your code like this:

var allSelectedItems = SP.ListOperation.Selection.getSelectedItems();
var item;
var itemEmails='mailto:';
var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var lists = web.get_lists();
var list = lists.getById(listGuid);
var i;
var items = [];

for (i = 0; i < allSelectedItems.length; i++){
    var selectedItemId = allSelectedItems[i].id;
    item = list.getItemById(selectedItemId);
    ctx.load(item);
    items.push(item);
    // push all the 'items' into an array 
    // these items are populated after the async call completes
}
ctx.executeQueryAsync(function() {
    // notice - 'function' means new scope.
    var i;
    var item;
    var title;

    for(i = 0; i < items.length; i++){
        item = items[i];
        title = item.get_item("E_x002d_Mail_x0020_1");
        console.log(title);
        itemEmails += title + ";";
    }
    // move this inside the success callback
    window.location.href = itemEmails;
}, function(){alert("error");

});
1

if you are showing that column in View, this code will work for you. I'm loading the Titles in the following code

    var data = ctx.ListData.Row;
    var selectedids = SP.ListOperation.Selection.getSelectedItems();

    var TitleIdMap = {};

    $.map(data,function(item,index){TitleIdMap[item.ID] = item.Title})//use E_x002d_Mail_x0020_1 in place of Title
    var selectedtitles = $.map(selectedids,function(item,index){return TitleIdMap[item.id]})

the "selectedtitles" gives you an array of selected item titles

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.