Repeating Table
A table with repeating rows stored in a single item column, with typed columns and summaries.
Widget description: repeatingTable
The Repeating Table lets users enter any number of rows with the same columns—such as budget items or order lines—directly inside the form. The entire table is stored in one multiline text column of the item as JSON. Unlike other widgets, it is therefore not virtual: it is a display mode of a multiline text field (Multiline Text). The sum of a selected column can be automatically written into a number field.
Adding to the Form
- In SharePoint, make sure your managed list has a Multiple lines of text column (plain text is recommended).
- In the designer palette on the Fields tab, drag this column into a section.
- In the inspector under Field display mode, switch from Multiline text to Table (JSON). The designer creates three sample columns (Item, Quantity, Price with sum).
- Edit the columns, add your own, and optionally configure sum syncing.
Switching back to Multiline text turns the field back into a regular text field. The table configuration remains saved in the config and is restored if you switch back.
Inspector Settings
| Option | Property | Meaning | Default |
|---|---|---|---|
| Field display mode | fieldType | multiline (Multiline text) or repeatingTable (Table JSON). | multiline |
| Table columns | repeatingTableConfig.columns[] | List of columns. Add a column by entering a name, choosing a type, and clicking "+"; remove it with the trash icon; reorder with arrows. At least one column is required. | Item, Quantity, Price |
| Edit column | columns[].label, type, required, width, summary, options, defaultValue | The pencil icon next to a column opens the editor: label, type, required flag, width (60 to 600 px), footer summary (number columns only), options (choice type, one per line), and default cell value. The column key (key) cannot be changed because data is stored under it. | per column |
| Minimum and maximum rows | repeatingTableConfig.minRows, maxRows | Minimum 0 to 100, maximum 1 to 500. Empty means unlimited. Maximum can never be set below minimum. | unlimited |
| Add row button label | repeatingTableConfig.addRowLabel | In another designer language, stored in translations (repeatingAddRowLabel), just like column headers (repeatingColumns). | Add row |
| Sync sum to field | repeatingTableConfig.syncSumToField | A form field of type Number, Currency, or Single line of text to receive the column sum. See Sum Syncing. Always visible in the inspector; if no suitable field exists on the form or the table has no number column, it is disabled with an explanation. | none |
| Custom label, Description, Width in section, Visible, Required, Read-only | customLabel, description, colSpan, defaultVisible, defaultRequired, defaultReadOnly | Common field options. Description appears under the label. A required table requires at least one row. |
When adding a column, the designer derives a key (key) from the name—for example, "Total Price" becomes total_price—and ensures it is unique. A number column gets a footer sum by default.
Columns and Types
Each column has the following properties:
| Property | Meaning |
|---|---|
id | Internal column identifier in the designer. |
key | Key in the row JSON. Must start with a letter or _ and contain only letters, digits, and _. Must be unique within the table. Renaming a key loses values in already-saved rows. |
label | Column header. |
type | text (text input), number (number), date (date picker, stored as YYYY-MM-DD), boolean (Yes/No checkbox), choice (dropdown from options). |
required | Required cell. An asterisk is shown in the header and validation rejects rows with an empty value. |
width | Column width in pixels (60 to 600). |
options | List of values for the choice type. |
defaultValue | Cell value in a newly added row. When omitted: number 0, boolean false, choice first option, otherwise empty. |
summary | Footer summary: none, sum, avg, min, max, count. |
The inspector lets you add a column, edit all of its properties, reorder it, and remove it; it also sets minRows, maxRows, and addRowLabel. When there are multiple number columns, sum syncing lets you pick which one to sum.
Summaries
A summary row is displayed below the data when at least one column has a summary and the table has at least one row. The cell displays the summary name in uppercase and the value, such as SUM: 1250.
| Summary | Result |
|---|---|
sum | sum of numeric values in the column |
avg | average, rounded to two decimal places |
min, max | minimum, maximum value |
count | number of rows |
none | no summary |
Non-numeric values are ignored in summaries. If there are no numbers, the result is 0. The first column without a summary in the summary row displays the label "Total".
Sum Syncing (syncSumToField)
You can automatically write a column's sum to a form field of type Number, Currency, or Single line of text, such as TotalBudget. Configure it in the inspector using Sync sum to field. The designer selects the first number column of the table as the source; once a target is chosen, a Column to sum selector appears so you can pick a different number column. Corresponding JSON:
"syncSumToField": {
"sourceColumnKey": "amount",
"targetFieldInternalName": "TotalBudget"
}
- The sum is recalculated and written on every user edit: changing a cell, adding, deleting, or moving a row. It is not written merely on opening the form.
- The target field is saved to SharePoint even if it is set to "Read-only". Locking it is recommended so the sum cannot be overwritten manually.
- Only numeric values are included in the sum.
- A Number or Currency target field receives a number. A Text target field receives the sum as a string without thousands separators and with a decimal dot (for example,
1500.5), keeping it machine-readable. - If you remove the target field from the form, the designer automatically clears the binding.
- In Display mode, nothing is recalculated.
Storage: JSON and Multiline Text
The field value is a JSON array of objects containing the column keys, for example:
[
{ "name": "License", "qty": 5, "price": 1200 },
{ "name": "Training", "qty": 1, "price": 8000 }
]
- Stored in SharePoint as text in a single multiline column, so you can also read it as JSON in list views and exports.
- On load, empty values,
[], and text wrapped in HTML tags produced by Enhanced Rich Text are tolerated. Invalid JSON is treated as an empty table. - A new row includes all columns with their default values. Rows created before new columns were added lack the new column key and render as empty.
- Do not store a table in a column limited to 255 characters (single line of text). Always use Multiple lines of text.
Invalid JSON in the column is displayed as an empty table. If a user adds a row and saves, the original text is overwritten. Therefore, do not write to the column manually.
Runtime Behavior
- New, Edit: table with input controls according to column types. An add-row button (label
addRowLabel, default "Add row") appears in the header and below the table. Each row has up/down arrows and a trash icon. An empty table displays the hint "No rows. Click …". - maxRows: once reached, the add buttons disappear. minRows: at this count, the trash icon is disabled.
- Display: read-only table without controls, with boolean values rendered as "Yes" and "No". An empty table shows "No rows".
- Validation on save: rows present in the value are counted (a newly added row with default empty cells counts). The value is validated the same way whether stored as a JSON string or an array.
- Required table: must have at least one row (or at least
minRows, if greater);maxRowsand required columns in every row apply. - Optional table: may remain empty (0 rows is always valid). Once it has at least one row,
maxRows, required columns in every row, andminRows(meaning "no rows, or at leastminRows") apply.
- Required table: must have at least one row (or at least
- The field is saved like any other item field (in Edit mode, only when modified by the user) and can be targeted by rules.
Text Translations
You can translate the label (customLabel), description (description), add-row button text (repeatingAddRowLabel), and column headers (repeatingColumns, keyed by column key or id). Options of a choice column are not translated. See Translations & Multilingual Forms.
Rules and Scripts
The table is a regular field, so standard actions apply:
- setVisible, setRequired, setReadOnly: show, require, or lock the table.
- setValue: writes the entire JSON string to the table (the value must be a valid JSON array, such as a row template).
- The table's value is a JSON string, so it is not suitable for rule conditions. Base conditions on the number field that receives the synced sum instead.
Configuration Example (JSON)
{
"internalName": "BudgetItems",
"customLabel": "Budget Items",
"description": "The sum of the Amount column is synced to Total Budget.",
"fieldType": "repeatingTable",
"colSpan": 12,
"repeatingTableConfig": {
"addRowLabel": "Add item",
"minRows": 1,
"maxRows": 50,
"syncSumToField": {
"sourceColumnKey": "amount",
"targetFieldInternalName": "TotalBudget"
},
"columns": [
{ "id": "col_name", "key": "name", "label": "Name", "type": "text", "required": true, "width": 260 },
{ "id": "col_type", "key": "type", "label": "Cost Type", "type": "choice",
"options": ["Labor", "Vendor", "License"], "defaultValue": "Labor" },
{ "id": "col_amount", "key": "amount", "label": "Amount", "type": "number",
"required": true, "defaultValue": 0, "summary": "sum" },
{ "id": "col_approved", "key": "approved", "label": "Approved", "type": "boolean" }
]
}
}
Limitations and Tips
- The table is designed for dozens of rows. The count is limited by
maxRows(up to 500) and the size of the multiline column. - In SharePoint, you cannot filter or aggregate individual rows of the column. For reporting, use the synced sum or a separate list with the Related Items widget.
- The schema requires at least one column and unique keys; otherwise the configuration fails validation.
- Removing a column does not delete its values from already-saved rows; they simply stop being displayed.
- Locking the table as "Read-only" prevents editing, and the sum is not recalculated while locked.