Infotables
An infotable is a zero-indexed, ordered array of objects that expose the same properties. Infotables can be represented in any programming language. On the ThingWorx Platform, infotables are commonly used in JavaScript implementations, and can be used to represent input values and output values for services. The ThingWorx Edge SDKs support infotables.
Because an infotable is an array of objects, it can also be thought of as a spreadsheet where the array entries are rows, and the object properties of each object in the array are the columns. When using infotables in a custom service or application, it is important that each object has the same properties, so that each column of the table maps to a property value.
How Do Arrays Work in JavaScript?
In ThingWorx, you can use JavaScript to create custom services using infotables for input and output. Arrays work in ThingWorx as they do in JavaScript. This section summarizes the basics if working with arrays.
To declare an array, you can use the following statements:

var myArray=new Array();
var mySecondArray=[];
Both of the above statements are equivalent. They both create array objects. An array can contain multiple objects in sequence of any type. For example:
var myArrayOfStuff=[“Pickel”,3,{name:”Bill”,phone:”555-555-1212”}];
The above array contains a string, a number, and a custom object with the fields name and phone. To try this out, use the Chrome browser and open the JavaScript Console (CTRL+SHIFT+J). Then paste in the line above to create this array, and try the following examples to access the items in the array. Below is a screen shot of the JavaScript console in Chrome, showing how to create and access each of the objects in the JavaScript array.
On line 2 above, the undefined value is not an error. Although the declaration of a local scope variable (var) returns the object undefined as a result, it does create the variable.
How is an Infotable Different from an Array?
In the example above, the JavaScript array contains completely different types of objects. Infotables can contain only one type of object. This type is defined, not with JavaScript's native object typing mechanism, but through the use of another ThingWorx-specific typing definition, called a Data Shape. JavaScript considers every type of object that is stored in an infotable to be of type Object, as you can see above when the command myArrayOfStuff[2] is printed out. Infotables require that each object in the array expose the exact same properties.
What is a Data Shape?
A Data Shape is a specification of the required property names and return types that each property of an "object" must have to be added to an infotable. Data Shapes also contain other metadata about a property that is useful for formatting and displaying the infotable in a tabular format or grid. You can declare Data Shapes in a ThingWorx Edge SDK application and in ThingWorx Composer. Data Shapes are required to build a functional infotable. Essentially they are a schema mechanism for defining the required fields of a Thing in ThingWorx. For more information about Data Shapes, see Data Shapes.
How to Use an Infotable with a Service?
The ThingWorx Edge Java SDK has tools for constructing infotables that are required for invoking services. This SDK provides the basis for showing how you can use an infotable with a service. Note that an INFOTABLE is one of the ThingWorx base types. In particular, it is an aggregate base type.
Services have arguments and return values that are expressed using primitives, such as string, integer, number, and boolean. An infotable can be used to describe a set of service arguments. Service parameters and return values can be passed and received as infotables that contain one or more rows.
When used in a ThingWorx Edge Java SDK application, an infotable has a DataShapeDefinition that describes the names, base types, and additional information about each field within the table. Data within an infotable is contained in rows. Each row can have one or more fields, described by the DataShapeDefinition of the infotable. Here is an example of an infotable definition, with its Data Shape and rows:
In addition to using infotables with services, you can use infotables to hold data for an event or the values that are returned by a read request for multiple properties. The infotable can contain one or more rows. When results are returned, you need to extract the values from each row, using the Java SDK methods, getFirstRow(), getSecondRow(), and so on. You also use a helper function that matches the base type for the field, such as getStringValue().
Here is an example of using an infotable to return the results of a property read:
// Define result as an InfoTable
InfoTable result

// Reading the "name" property of a Thing and
// extracting the results from an InfoTable
// Since "name" is a STRING, use getStringValue()
// to return the value of the "name" property.
result = client.readProperty(ThingworxEntityTypes.Things,
ThingName, "name", 10000);
String name = result.getFirstRow().getStringValue("name");
For more information about Data Shapes and infotables with the ThingWorx Edge Java SDK, see http://support.ptc.com/help/thingworx_hc/thingworx_edge_sdks_ems/#page/thingworx_edge_sdks_ems%2Fjava_sdk%2Fc_javasdk_data_shapes.html.
From ThingWorx 8.5.6 and later, to update field values for single/ multiple row infotables, create a local variable, perform the infotable operation, and then set it back to the Thing infotable property.
var tempInfoTable = me.infoTableProperty;
tempInfoTable.AddRow(row);
me.infoTableProperty = tempInfoTable;
Referencing an Infotable Property in a Custom Service
There are two ways to access an infotable property through the use of the "me" keyword. The first option is to use a method that allows for a direct object reference on the infotable property. The second way is to use a method that only references the value. It is important to ensure you understand the difference, in order to prevent data corruption that can result from doing a direct reference. This section describes both options.
* 
While there are other APIs you can use to obtain a property value in a custom service, the purpose of this section is to describe what to do when using the "me" keyword.
The first method allows for direct object reference on that infotable property. Any change made to a row will be reflected directly on that property. Any change made to a field will be restricted and needs to be done through another method that is explicitly changing the data shape that the infotable property is referencing. Direct object reference can be done like the following example:
// Get a direct reference to the infoTableProperty on the entity
var infoTableProperty = me.infoTableProperty;

// Create a new NamedVTQ entry object to add to the infotable
var newEntry = new Object();
newEntry.name = "TemperatureReading"; // STRING [Primary Key]
newEntry.time = Date.now(); // DATETIME
newEntry.value = 98.6; // VARIANT
newEntry.quality = "GOOD"; // STRING

// Add the newEntry object as a new row to the infotable property
infoTableProperty.AddRow(newEntry);
// At this point, the property on the entity has a new row added to it
The property named infoTableProperty on the Thing will be assigned directly to the tempTable variable. Any changes made to tempTable will be reflected back on the infoTableProperty. Keep in mind that if multiple services that access this property value are exercised at the same time, results may be unexpected upon viewing that infotable property again. The safest way to modify an infotable property, to ensure the property value will be set to the value that is anticipated, is the second method.
The second method only references the value, not the actual property object. By only referencing the value, any changes made to rows or fields will be accepted, but will not be reflected on the property directly. Referencing only the infotable property's value can be done through the use of the Clone API service:
var params = {
t1: me.infoTableProperty /* INFOTABLE */
};
// result: INFOTABLE
var infoTableProperty = Resources["InfoTableFunctions"].Clone(params);

// NamedVTQ entry object
var newEntry = new Object();
newEntry.name = "TemperatureReading"; // STRING [Primary Key]
newEntry.time = Date.now(); // DATETIME
newEntry.value = 98.6; // VARIANT
newEntry.quality = "GOOD"; // STRING

// Add the newEntry object as a new row to the infotable property
infoTableProperty.AddRow(newEntry);

// At this point, you'll need to set the cloned table back to the infoTableProperty on the entity if you want the row to be added
me.infoTableProperty = infoTableProperty;

// Can also return the clone if desired
var result = infoTableProperty;
Using VEC Base Types
When using properties with the base type VEC2, VEC3 or VEC4, you cannot set the coordinate values within a custom service with the setX() or setY() methods. To set the coordinate values, you must set a JSON as the property value such as {"x": 2, "y": 4}. You cannot use dot notation such as .x = 2 or .y = 4.
Was this helpful?