Repeater Field Type

Renders a custom TrRepeater Component inside the block

The type we would use inside the schema’s field_meta property to render this field is “repeater”: "type": "repeater"

If you haven’t already, we suggest you read the “model.json file” and “Field Types” pages before continuing.

The repeater field type can be used to repeat (to create an array of) either one or more Fields (Field Types).

It can also have another repeater element as a Field Type that’s been repeated, with a limitation that the inner (repeated) repeater can’t have any more nested repeaters. So the maximum level of nesting is 2.

That inner repeater can, of course, wrap one or more Field Types of any type other than the repeater type. Here are a few example configurations/screenshots of simple and a bit complex repeater configurations (schemas).

Apart from being used to repeat elements, this field can be used as a “pseudo group” which we will explain later.

Minimum Schema needed to create the field (example)

"titles": {
  "type": "array",
  "field_meta": {
    "type": "repeater",  
    "label": "Titles",
    "subfields": {
      "title": {
        "type": "object",
        "field_meta": {
          "type": "text",
          "label": "Title"
        },
        "default": {
          "text": ""
        }
      }
    }
  },
  "default": []
}

This snippet of code will generate a repeater control. The field name will be “titles”, its label will be “Titles” and it will have an empty array as a default value. This example only repeats one Text Field type (Title), but, as mentioned above, it can repeat more Field Types.

As we can see in the schema above, the field_meta property on the repeater Field Type contains a nested subfields property. This is the place where we would place all the nested fields that we want to use. This is a required property.

What it would look like inside the block in the editor.

Simple Repeater Field Example - Theme Redone | webredone

As we can see from the GIF above, the simple Schema we defined for the repeater field inside the model.json file generates the wrapper repeater component. The repeater component by default allows us to add/remove, reorder, and collapse/un-collapse repeated items.

Rendering field’s data on the front-end:

<div n:if="!empty($titles)">
  <h2
    n:foreach="$titles as $item"
    n:ifcontent
  >
    {$item['title']['text']}
  </h2>
</div>

Repeater field with multiple sub-fields (example)

"fields": {
  "type": "array",
  "field_meta": {
    "type": "repeater",
    "label": "Fields",
    "subfields": {
    "title": {
      "type": "object",
      "field_meta": {
        "type": "text",
        "label": "Title"
      },
      "default": {
        "text": ""
      }
    },
    "cta": {
      "type": "object",
        "field_meta": {
          "type": "cta",
          "label": "CTA"
        },
        "default": {
          "title": "",
          "url": "",
          "target": false
        }
      },
      "image": {
        "type": "object",
          "field_meta": {
            "type": "image",
            "label": "Image"
          },
          "default": {
            "src": "",
            "id": null
          }
        }
      }
    },
    "default": []
  }
}

Theme Redone Repeater Field Type - multiple nested fields example

<div n:if="!empty($fields)">
  <div
    n:foreach="$fields as $item" 
  >
    <h2 n:ifcontent>{$item['title']['text']}</h2>
    {tr_a($item['cta'], "btn btn--brand")}
    {if isset($item['image']) && $item['image']['src']}
      {tr_get_media($item['image'])}
    {/if}
  </div>
</div>

Repeater field with a nested repeater sub-field (example)

"fields": {
  "type": "array",
  "field_meta": {
    "type": "repeater",
    "label": "Fields",
    "subfields": {
      "title": {
        "type": "object",
        "field_meta": {
          "type": "text",
          "label": "Title"
        },
        "default": {
          "text": ""
        }
      },
      "cta": {
        "type": "object",
        "field_meta": {
          "type": "cta",
          "label": "CTA"
        },
        "default": {
          "title": "",
          "url": "",
          "target": false
        }
      },
      "nested_repeater_items": {
        "type": "array",
        "field_meta": {
          "type": "repeater",
          "label": "Nested Repeater Items",
          "subfields": {
            "nested_title": {
              "type": "object",
              "field_meta": {
                "type": "text",
                "label": "Nested Title"
              },
              "default": {
                "text": ""
              }
            }
          }
        },
        "default": []
      }
    }
  },
  "default": []
}

Repeater Field type with a nested repeater field type example screenshot | webredone | wordpress starter theme

<div
  n:if="!empty($fields)"
  n:foreach="$fields as $item"
>
  <h2 n:ifcontent>{$item['title']['text']}</h2>
  {tr_a($item['cta'], "btn btn--brand")}
  <h3
    n:foreach="$item['nested_repeater_items'] as $sub_item"
    n:ifcontent
  >
    {$sub_item['nested_title']['text']}
  </h3>
</div>

field_meta properties

Besides the optional properties help (explained on Field Types page), and col (explained on model.json page), this field type has a few more field_meta required and optional properties.

Those properties are:

  1. subfields – required
  2. grid – optional
  3. grid_gap – optional
  4. disable_reordering – optional
  5. repeater__item__label – optional
  6. repeater__item__help – optional
  7. max_rep – optional
  8. min_rep – optional

subfields

subfields property is an object where we would place all the nested fields that we want to use. This is a required property.


grid

Similar to how we are using the grid and col properties on the root level Fields, we can use the grid optional property on the repeater field itself. The only difference is that the grid for the root level fields is defined inside the block_meta property of the main model.json file. Besides that, the repeater’s grid property accepts an integer as a value as opposed to the root level grid that accepts a string of 3 predefined options, as described on the model.json page.

By default, and, if this property is not defined, repeater items will be stacked vertically. By using this property, we can change that. Here’s a quick example (We’ll use the first example schema from the top of this page).

...
"titles": {
  "type": "array",
  "field_meta": {
    "type": "repeater",
    "label": "Titles",
    "grid": 3,
    "subfields": {
      "title": {
        "type": "object",
        "field_meta": {
          "type": "text",
          "label": "Title"
        },
        "default": {
          "text": ""
        }
      }
    }
  },
  "default": []
}
...

repeater field type with the grid property set to 3


grid_gap

Vertical space between items (cells). If grid property is used, it also affects horizontal spacing. It accepts integer as a value. Default is 10 if not defined.

...
"grid_gap": 20,
...

disable_reordering

By default, repeater items can be reordered by clicking on the arrow left/right icons that are visible in the header of each repeater item. This can be disabled by defining the disable_reordering property and setting its value to true. Doing this will remove the arrow icons and disable this feature.

...
"disable_reordering": true,
...

repeater__item__label

Theme Redone repeater item label

From the screenshot above we can see that the default label for each repeater item (group wrapping the actual field/s) is “Item”. We can overwrite that via the repeater__item__label property. In this example, we have a repeater where each repeater item has only the title field. If we do this…

...
"repeater__item__label": "Title",
...

… now, instead of the generic “Item”, the labels for each repeater item as well as for the Add button are replaced with “Title”.
Custom repeater item label


repeater__item__help

...
"repeater__item__help": "This is a help text tooltip defined for each repeater item.",
...

This optional property allows us to define a tooltip that will show for each repeater item.

theme-redone optional repeater item tooltip


max_rep

Optional property. By default, the maximum number of items that can be added to a repeater field is set to 100.
This can be overwriten by defining the max_rep property and setting its value to an integer.

...
"max_rep": 5,
...

repeater item max_rep property

Notice, how, once we get to the maximum number of allowed repeater items, the “Add” button disappears.


min_rep

Controls the minimum number of items that the repeater can have. By default, this is 0.

...
"min_rep": 2,
...

This property is a bit different from the max_rep one because it expects a bit more configuration in order for the repeater not to break.

Up until now, we’ve been setting the repeater’s default property to an empty array []. In order for min_rep to work, we would need to change that, and let’s say that our titles repeater needs a minimum of 2 items in order for it to work on the front-end; This is how we would write the Schema.

...
"titles": {
  "type": "array",
  "field_meta": {
    "type": "repeater",
    "label": "Titles",
    "min_rep": 2,
    "max_rep": 4,
    "subfields": {
      "title": {
        "type": "object",
        "field_meta": {
          "type": "text",
          "label": "Title"
        },
        "default": {
          "text": ""
        }
      }
    }
  },
  "default": [
    {
      "title": {
        "text": ""
      }
    },
    {
      "title": {
        "text": ""
      }
    }
  ]
}
...

This example only has a Title subfield that’s of the text type. For each of the repeater items (taking into account the min_rep), we need to manually populate the repeater’s default array. In the case where each repeater item contains multiple subfields, we would need to add them inside the same object where the title is written (for each repeater item). At a minimum, we need to do this min_rep number of times, but, if we want, we can prepopulate more than 2 (in this example); We can prepopulate all the repeater items. In this case, we’ve also set the max_rep property to 4, so that’s also the maximum count of objects we can prepopulate.


Repeater as a “Pseudo Group”

Earlier on this page, we’ve said that we can use the repeater field as a “pseudo group”. We can do that with the combination of the min_rep and max_rep properties.
Say we know we have 3 columns on the front-end (or 3 cards). The number can’t vary. It will always be 3. Each of the cards will have a title, text, and link fields. This is how we would achieve this.

"cards": {
  "type": "array",
  "field_meta": {
    "type": "repeater",
    "label": "Cards",
    "repeater__item__label": "Card",
    "min_rep": 3,
    "max_rep": 3,
    "grid": 3,
    "subfields": {
      "title": {
        "type": "object",
        "field_meta": {
          "type": "text",
          "label": "Title"
        },
        "default": {
          "text": ""
        }
      },
      "text": {
        "type": "object",
        "field_meta": {
          "type": "text",
          "label": "Text",
          "max_chars": 100
        },
        "default": {
          "text": ""
        }
      },
      "cta": {
        "type": "object",
        "field_meta": {
          "type": "cta",
          "label": "CTA",
          "help": "Optional (Leave url field empty if you don't want to show the button)"
        },
        "default": {
          "title": "",
          "url": "",
          "target": false
        }
      }
    }
  },
  "default": [
    {
      "title": {
        "text": ""
      },
      "text": {
        "text": ""
      },
      "cta": {
        "title": "",
        "url": "",
        "target": false
      }
    },
    {
      "title": {
        "text": ""
      },
      "text": {
        "text": ""
      },
      "cta": {
        "title": "",
        "url": "",
        "target": false
      }
    },
    {
      "title": {
        "text": ""
      },
      "text": {
        "text": ""
      },
      "cta": {
        "title": "",
        "url": "",
        "target": false
      }
    }
  ]
}
...

This Schema will generate this UI.
theme redone repeater field used as a group

Optionally, we could also use the "disable_reordering": true, to lock the cards.

Join Our Newsletter

To get updates about Theme Redone