Tuesday, April 19, 2016

Avoid “Value does not fall within the expected range” error when read list item with taxonomy fields via javascript in Sharepoint Online

When list contain many taxonomy fields and you try to read list item with all these fields using CAML query in javascript:

   1: var ctx = SP.ClientContext.get_current();
   2: var list = ctx.get_web().get_lists().getByTitle("MyList");
   3: var query = new SP.CamlQuery();
   4: query.set_viewXml('<View>' +
   5:                       '<Query>' +
   6:                           '<Where>' +
   7:                           '</Where>' +
   8:                       '</Query>' +
   9:                       '<RowLimit>1</RowLimit>' +
  10:                   '</View>');
  11: var items = list.getItems(query);
  12: ctx.load(items, 'Include(Field1,Field2,Field3,...)');
  13: ctx.executeQueryAsync(Function.createDelegate(this, function (sender, args) { /* */ }),
  14:     Function.createDelegate(this, function (sender, args) { console.log("Error: " +
  15:         args.get_message() + "\n" + args.get_stackTrace()); }));

you may get the following error:

Value does not fall within the expected range error

It happens because of List Lookup Threshold Limit which is set to 12 in Sharepoint Online (see Increased site collection and list lookup limits). In order to avoid this error use the following workaround: at first read necessary item to get it’s id. Then load this item using List.getItemById method which will return list item containing all fields without need to explicitly enumerate them in “Include(…)” statement:

   1: var ctx = SP.ClientContext.get_current();
   2: var list = ctx.get_web().get_lists().getByTitle("MyList");
   3: var query = new SP.CamlQuery();
   4: query.set_viewXml('<View>' +
   5:                       '<Query>' +
   6:                           '<Where>' +
   7:                           '</Where>' +
   8:                       '</Query>' +
   9:                       '<RowLimit>1</RowLimit>' +
  10:                   '</View>');
  11: var items = list.getItems(query);
  12: ctx.load(items);
  13: ctx.executeQueryAsync(
  14:     Function.createDelegate(this, function (sender, args) {
  15:         getPropsSuccess(ctx, list, items);
  16:     }),
  17:     Function.createDelegate(this, function (sender, args) {
  18:         console.log("Error: " + args.get_message() + "\n" + args.get_stackTrace());
  19:     })
  20: );
  21:  
  22: function getPropsSuccess(ctx, list, items) {
  23:     var itemId = null;
  24:     var enumerator = items.getEnumerator();
  25:     while (enumerator.moveNext()) {
  26:         var item = enumerator.get_current();
  27:         itemId = item.get_id();
  28:         break;
  29:     }
  30:  
  31:     if (itemId == null) {
  32:         return;
  33:     }
  34:  
  35:     var item = list.getItemById(itemId);
  36:     ctx.load(item);
  37:     ctx.executeQueryAsync(
  38:         Function.createDelegate(this, function (sender, args) {
  39:             // here you may get values of all fields in the list
  40:             // item.get_item("Field1"), item.get_item("Field2"), item.get_item("Field3"), ...
  41:         }),
  42:         Function.createDelegate(this, function (sender, args) { console.log("Error: " +
  43:             args.get_message() + "\n" + args.get_stackTrace()); }));
  44: },

In this example we read all items from the list first and get id of the 1st item only, but you may retrieve item using your own criteria of course by specifying appropriate CAML query. With this approach it is possible to get values of all fields from the list in list item.

No comments:

Post a Comment