# Repeater

Repeater field is one of the most powerful Alchemy Options fields. Alongside the [Sections](https://docs.alchemy-options.com/v0.9/fields/sections) and [Field Group](https://docs.alchemy-options.com/v0.9/fields/field-group) fields it groups fields and allows to [produce arrays of values](#return-value).

## Features:

* Can be [sorted by drag-and-drop](#sorting).
* Can [temporarily remove values](#temporary-hiding) from the front end.
* Can [copy items](#copying-a-repeatee).
* Can repeat items of [different types](#typed-repeaters).

2 things were taken as the pillars of a repeater:

1. [Reusability](#reusing-the-repeaters-signature) of a repeater's signature (both in Options and [Meta Boxes](https://docs.alchemy-options.com/v0.9/meta-boxes))
2. Possibility to [nest repeaters](#nested-repeaters) into one another

Thus a repeater field consists of 2 parts: a) the field itself and b) its signature (like a mould for the field).

## Repeater signatures

All repeater signatures should be specified in their own config in the `init` callback. Like so:

```php
function add_custom_repeaters() {
    if( ! class_exists( 'Alchemy_Options\Includes\Repeaters' ) || wp_doing_ajax() ) {
        return;
    }

    $repeaters = array(
        array(
            'id' => 'repeater-one',
            'fields' => array(
                array(
                    'title' => 'My content title',
                    'desc' => 'Short description for the field',
                    'id' => 'description',
                    'type' => 'editor',
                ),
            ),
        ),
    );

    new Alchemy_Options\Includes\Repeaters( $repeaters );
}

add_action( 'init', 'add_custom_repeaters' );
```

Each signature is an array with [`id` and `fields` keys](#signature-params). Much like the [Field Group](https://docs.alchemy-options.com/v0.9/fields/field-group) field.

The fields themselves are added just like any other fields in the `options` part of the main config with one exception - the type of the field should be in the following format: `repeater:signatureID`.

Since the [Sections](https://docs.alchemy-options.com/v0.9/fields/sections) field is primarily for aesthetic grouping, it cannot be used within the Repeater.

Enough talking, let's see some code :)

## Example configuration

Considering we have the [signatures](#repeater-signatures) as above.

```php
...
'options' => array(
    array(
        'title' => 'My repeater field title',
        'id' => 'repeater-field',
        'desc' => 'Short description for the field',
        'type' => 'repeater:repeater-one',
        'tab' => 'homepage',
    ),
),
...
```

This will produce the following

![](https://2720448264-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKMTiOPVR7pXWhebz7q%2Fsync%2F4c6a92630983564225c5c56b0d14bb5f4d89a50b.png?generation=1602624634739038\&alt=media)

Doesn't look like much unless you click the `Add new` button which will result in the following

![](https://2720448264-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKMTiOPVR7pXWhebz7q%2Fsync%2F7d88f0eff071aaf351f42fa5e1c52f2ced7792e4.png?generation=1602624635054927\&alt=media)

Thus pressing the `Add new` button again and again will generate as many items (a.k.a. 'repeatees') as needed.

Note that although I've specified one field in the configuration above (which is the [Editor field](https://docs.alchemy-options.com/v0.9/fields/editor)) **2** of them are present on the screenshot. The `title` field is there by default and will show the value in the title bar of the repeatee as soon as you type something in. Repeatees would have been harder to distinguish if they weren't 'labeled'.

![](https://2720448264-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKMTiOPVR7pXWhebz7q%2Fsync%2Fb7c5e597f409a2f56e25e8adb2bb14d921f4dc62.png?generation=1602624635328983\&alt=media)

## Sorting

Single click on the toolbar will toggle the visibility of the item, while click and drag will allow to sort

![](https://2720448264-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKMTiOPVR7pXWhebz7q%2Fsync%2Ff755ea007ef461455a5a44993d57852c34478081.png?generation=1602624635163601\&alt=media)

You can sort 'closed' items or 'open' it doesn't matter.

## Temporary hiding

If you hover over or expand a repeatee there's a button group that allows to delete or to temporarily hide it. If you press the `Hide` button, the repeatee's value will not be included in the return value and the item itself will indicate that it's hidden.

![](https://2720448264-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKMTiOPVR7pXWhebz7q%2Fsync%2Ff95ac9df56082c2057c0a5fcf0d349c26aaf8469.png?generation=1602624635762822\&alt=media)

## Copying a repeatee

If you press the Copy button, it'll work as expected and will produce an exact copy of the repeatee below it. If the target repeatee is hidden, the resulted copy will be hidden as well.

## Reusing a repeater's signature

Since repeaters' signatures are defined in their own config it allows developers to reuse a repeater's signature to create several repeater fields.

E.g. the following configuration

```php
...
'options' => array(
    array(
        'title' => 'My repeater field title',
        'id' => 'repeater-field',
        'desc' => 'Short description for the field',
        'type' => 'repeater:my-repeater',
        'tab' => 'homepage',
    ),
    array(
        'title' => 'Another repeater field',
        'id' => 'repeater-field-two',
        'desc' => 'Short description for the field',
        'type' => 'repeater:my-repeater',
        'tab' => 'homepage',
    ),
),
...
```

will create two separate repeater fields with identical fields using the same signature

![](https://2720448264-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKMTiOPVR7pXWhebz7q%2Fsync%2Fb4015812fc1a27eeff3e0772aa08da1849427d15.png?generation=1602624636191300\&alt=media)

## Nested repeaters

You can nest repeaters, make sure that the repeaters' signatures are not nested. Here's an example of a repeater inside a repeater inside a repeater (that's right - 3 levels deep)

### Repeaters signatures:

```php
...
    array(
        'id' => 'my-repeater',
        'fields' => array(
            array(
                'title' => 'My upload title',
                'id' => 'upload',
                'desc' => 'Short description for the field',
                'type' => 'repeater:upload-repeater',
            ),
        ),
    ),
    array(
        'id' => 'upload-repeater',
        'fields' => array(
            array(
                'title' => 'My upload title',
                'desc' => 'Short description for the field',
                'id' => 'upload',
                'type' => 'upload',
            ),
            array(
                'title' => 'My select title',
                'id' => 'checks',
                'desc' => 'Short description for the field',
                'type' => 'repeater:select-repeater',
            ),
        ),
    ),
    array(
        'id' => 'select-repeater',
        'fields' => array(
            array(
                'title' => 'My upload title',
                'desc' => 'Short description for the field',
                'id' => 'select',
                'type' => 'select',
                'choices' => ['Label one', 'Label two', 'Label three']
            ),
        ),
    ),
...
```

### Options:

```php
...
'options' => array(
    array(
        'title' => 'My repeater field title',
        'id' => 'repeater-field',
        'desc' => 'Short description for the field',
        'type' => 'repeater:my-repeater',
        'tab' => 'homepage',
    ),
),
...
```

![](https://2720448264-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKMTiOPVR7pXWhebz7q%2Fsync%2F6781ee4a13df05cc7b7370e2f70e277c325a7a5b.png?generation=1602624635775897\&alt=media)

Note that all 3 different signatures are top level (not nested) but the `fields` part reference them. Thus creating the needed nesting.

## Typed repeaters

A repeater field can repeat values of different types. It has a slightly different config signature that has `field-types` instead of `fields` in it. Each `field-type` should have a unique `id`, nice `title` (that will be seen on the front end) and the `fields` key that has regular options settings. E.g.

### Repeaters signatures:

```php
...
array(
    'id' => 'my-repeater',
    'field-types' => array(
        array(
            'id' => 'wysiwyg',
            'title' => 'Description as a WYSIWYG',
            'fields' => array(
                array(
                    'title' => 'Editor',
                    'id' => 'editor',
                    'type' => 'editor',
                ),
            ),
        ),
        array(
            'id' => 'textarea',
            'title' => 'Description as a textarea',
            'fields' => array(
                array(
                    'title' => 'Editor',
                    'id' => 'editor',
                    'type' => 'textarea',
                ),
            ),
        ),
    ),
),
...
```

### Options:

```php
array(
    'title' => 'My from-type repeater',
    'desc' => 'Choose which type to add',
    'id' => 'from-type-repeater',
    'type' => 'repeater:my-repeater',
),
```

These settings will produce the following:

![](https://2720448264-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKMTiOPVR7pXWhebz7q%2Fsync%2Fcd5ed09228323d663fd1b5aed0547822bc001fef.png?generation=1602624635955614\&alt=media)

Clicking any of the types will produce repeatees of the respective type. Since it's a repeater field you can mix and match repeatees of various types under one option ID.

![](https://2720448264-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKMTiOPVR7pXWhebz7q%2Fsync%2Fe965a89093b31a682cb79e95ea320ab6b0ae0542.png?generation=1602624636607918\&alt=media)

Kinda nice, huh? :)

## Params

| Name    | Type   | Description                                                                                                             |
| ------- | ------ | ----------------------------------------------------------------------------------------------------------------------- |
| `type`  | string | `repeater:signatureID`. [Signature ID](#repeater-signatures) should match one from the repeaters config. **(required)** |
| `id`    | string | Unique ID that will be used to retrieve the value **(required)**                                                        |
| `tab`   | string | Specifies in which tab this option will be rendered                                                                     |
| `title` | string | Shows a heading to the left of the field                                                                                |
| `desc`  | string | Shows a description text (can have HTML)                                                                                |

## Simple signature params

| Name     | Type   | Description                                                                                                                                                                                     |
| -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`     | string | Unique ID that will be used in the `type` parameter of the field **(required)**                                                                                                                 |
| `fields` | array  | Array of fields usual configurations. Can have [nested repeater fields](#nested-repeaters). Ignores the [Sections](https://docs.alchemy-options.com/v0.9/fields/sections) field. **(required)** |

## Typed repeater signature params

| Name          | Type   | Description                                                                                                                                                                   |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`          | string | Unique ID that will be used in the `type` parameter of the field **(required)**                                                                                               |
| `field-types` | array  | Configurations for each repeatee type, which is an array consisting of the required `id`, `title` and `fields` keys. See [an example](#typed-repeaters) above. **(required)** |

## Return value

Repeater field returns an array of associative arrays where array keys are the signature's fields IDs. The results will not include the [hidden repeatees](#temporary-hiding).

A nested sample config above may return something as follows:

```php
Array
(
    [0] => Array
        (
            [title] => Level one
            [upload] => Array
                (
                    [0] => Array
                        (
                            [title] => Level two
                            [upload] =>
                            [checks] => Array
                                (
                                    [0] => Array
                                        (
                                            [title] => Level three
                                            [select] => Label one
                                        )
                                )
                        )
                )
        )
    [1] => Array
        (
            [title] => Another field
            [upload] => Array
                (
                )
        )
)
```

## Typed repeaters return value

Typed arrays return an array with `type` and `value` fields, `type` is the field type ID you specified in the settings and `value` is a regular repeater return value.
