A Data Grid holds table-style data such as the lines of an expense report. These examples total a column, number the rows, use values within a row, and fill a grid from another grid.
How grid data is stored
A Data Grid's value is a list of rows. Each row holds the values of the components inside the grid, by property name. For a grid expenseLines containing a Currency component expenseAmount:
-
data.expenseLinesis the list of rows. -
data.expenseLines[0].expenseAmountis the amount on the first row. -
In a script on a component inside the grid,
rowholds the current row, sorow.expenseAmountis the amount on the same row.
Number and Currency components store numbers, so they can be added directly. A new Data Grid starts with one empty row.
Total a column
Add a Currency component outside the grid for the total. On its Data tab, under Calculated Value → JavaScript Value, enter:
var total = 0;
(data.expenseLines || []).forEach(function (line) {
total += Number(line.expenseAmount) || 0;
});
// Round to cents.
value = Math.round(total * 100) / 100;
Change expenseLines and expenseAmount to your own property names. The same loop can calculate averages, counts or anything else across the rows.
Number the rows
Add a Number component inside the Data Grid. As its calculated value, enter:
value = data.expenseLines.indexOf(row) + 1;
To start at a number the user enters (startNumber) and count in steps (stepBy), both outside the grid:
var index = data.expenseLines.indexOf(row);
value = (Number(data.startNumber) || 1) + index * (Number(data.stepBy) || 1);
Row numbering works in a Data Grid. Don't use it in an Edit Grid: rows loaded from a saved submission show 0.
Calculate within a row
Components inside a grid can use other values from the same row. For a line total from quantity and unit price:
value = (Number(row.quantity) || 0) * (Number(row.unitPrice) || 0);
To copy one value in the row to another:
value = row.requestedAmount || null;
Fill a grid from another grid
Copy rows from one grid (employees, with first and last) into a second grid (badges, with firstName and lastName). Use a button so the copy happens when the user asks for it. In the button's Button Custom Logic:
// Empty the target grid, then add one row for each source row.
data.badges = data.badges || [];
data.badges.length = 0;
(data.employees || []).forEach(function (employee) {
data.badges.push({
firstName: employee.first,
lastName: employee.last
});
});
Each object added becomes a new row. Its property names must match the property names of the components in the target grid.