Repeater
4 min read
A Repeater lets editors add as many rows as they need, each row holding the same set of sub-fields (question and answer, name and photo, feature and price). All rows are stored as one JSON list.
Type id |
|
Builder category | Layout |
Column |
|
Returns | a list of row arrays, or |
Prints | an ordered list of the rows |
Repeaters are built like Groups: add the field, then + Add sub-field for each column of the row. The same rules apply to what may go inside (no Group, no Repeater, no Password, no Pro types) and to field keys.
For many records, or when you want to filter and sort by their values, use a normal field group or a Pro data table; a repeater is meant for a few dozen rows that are shown together.
Type settings
Setting | Default | Effect |
|---|---|---|
Minimum rows | 0 | Editors cannot remove rows below this number (the remove button is disabled). It does not add empty rows for them and is not enforced on the server. It cannot exceed Maximum rows. |
Maximum rows | 0 | 0 means no limit, up to the built-in cap of 200 rows. When the maximum is reached, Add row and Duplicate row are disabled, and extra rows posted by a script are dropped on save. |
Button label | Add row | Text of the button that adds a row. Empty uses "Add row". |
Edit screen
- A bar shows the row count ("3 rows", or "2 / 3 rows" with a maximum) and Collapse all.
- Each row has a header with a drag handle (Drag to reorder), the row number (click to collapse or expand the row) and buttons Duplicate row, Move row up, Move row down and Remove row. Collapsed rows show a short summary.
- With no rows the message reads: "No rows yet. Use “Add row” to add the first one." (using your button label).
- Press the add button (default Add row) to append a row.
Rows are reordered with the drag handle or the up and down buttons. In front-end forms (Pro) the rows have plain arrow and remove buttons.
What is saved
- Rows are saved in the order shown, renumbered from 0.
- Each sub-field is cleaned by its own type.
- Empty rows are dropped. A row counts as empty when every sub-value is empty; a True / false sub-field that is off does not make a row worth keeping on its own.
- Rows beyond Maximum rows are dropped (the first ones are kept).
- A required Repeater needs at least one row with a filled sub-field; required sub-fields are checked in every row and the notice names the first one (
Rows › Name). - Saving every row away clears the field.
- If the form would send more values than the server accepts (
max_input_vars), saving is blocked in the browser ("Saving is blocked: this screen would send more values than the server accepts…"); if it still reaches the server, none of the custom fields of that save are written and an error notice says "Custom fields were not saved: the form sent more values than the server accepts…". Remove rows or ask your host to raise the limit.
From code, pass a list of rows. A row's missing sub-fields are simply absent:
wpmcf_update_field( 'faq', 'items', [
[ 'question' => 'What is it?', 'answer' => 'A plugin.' ],
[ 'question' => 'Is it free?' ],
], $post_id );As with a Group, writing replaces the whole list.
Template usage
$rows = wpmcf_get_field( 'faq', 'items' );
// [
// [ 'question' => 'What is it?', 'answer' => 'A plugin.', 'featured' => 1 ],
// [ 'question' => 'Is it free?' ],
// ]
if ( $rows ) {
foreach ( $rows as $row ) {
printf(
'<details><summary>%s</summary>%s</details>',
esc_html( $row['question'] ?? '' ),
wp_kses_post( $row['answer'] ?? '' )
);
}
}Rows are numbered from 0 in code. Sub-values are the stored values (a True / false sub-field is 1/0, an Image is an attachment ID, a Link is an array). Keys inside a row have no guaranteed order and missing keys are possible, so use ??.
Read one row or one cell with path:
wpmcf_get_field( 'faq', 'items', null, [ 'path' => '0' ] ); // the first row (array)
wpmcf_get_field( 'faq', 'items', null, [ 'path' => '1.question' ] ); // "Is it free?"Printing
wpmcf_the_field() and the shortcode print an ordered list, with each sub-value formatted by its own type (labels for selects, linked titles for relations, an <img> for images). Empty sub-values are left out.
[wpmcf_field group="faq" field="items" wrap="false"]<ol class="wpmcf-repeater">
<li class="wpmcf-repeater__row">
<span class="wpmcf-repeater__value" data-field="question">What is it?</span>
<span class="wpmcf-repeater__value" data-field="answer">A plugin.</span>
</li>
<li class="wpmcf-repeater__row">
<span class="wpmcf-repeater__value" data-field="question">Is it free?</span>
</li>
</ol>- Print one row:
path="1". Print one cell:path="1.question"(formatted by the sub-field's type, using the sub-field's own prefix, suffix and wrapper). - Developers can change the whole list with the
wpmcf/field/repeater_htmlfilter (arguments: the HTML, the rows, the field definition). - By default the output sits inside
<span class="wpmcf-field-value">; usewrap="false"to avoid a list inside a span.
For custom markup, loop over the array as shown above. Page-builder widgets for repeaters (Elementor) are part of Pro; see Pro builder widgets.
Limits
- Maximum 200 rows per repeater.
- A Repeater cannot contain a Group or another Repeater, and cannot sit inside a Group.
- The whole list is one value: filtering posts by what is inside a row cannot use an index and sorting by it is not possible, so use top-level fields for values you query.
- A Repeater cannot be a Programmatic SEO data source column.
Troubleshooting
- My empty row disappeared after saving. Rows with no filled sub-field are dropped.
- I cannot remove the last row. Minimum rows is set.
- Rows beyond 3 vanish. Maximum rows is 3.
- "Custom fields were not saved: the form sent more values than the server accepts." The server's
max_input_varswas exceeded; remove rows or sub-fields, or raisemax_input_varsin PHP.
Still stuck? Contact support