# Repeater

## Form Repeater Component

Form Repeater component is analog of loops from programming languages.

### Properties

| Property            | Required | Available values                  | Default Value | Example                                                                     | Description                                     |
| ------------------- | -------- | --------------------------------- | ------------- | --------------------------------------------------------------------------- | ----------------------------------------------- |
| field\_name         | yes      | `string`                          | -             | `"data.agents"`                                                             | Name of the array field.                        |
| components          | yes      | `array` of component definitions. | -             | `[{"type":"form-input", {"config": {"field_name": "data.agents.*.name"}}}]` | Repeatable component definitions.               |
| select\_field\_name | no       | `string`                          | -             | `"data.agent_index"`                                                        | Name of the selected index field.               |
| fixed\_length       | no       | `number` or jsonlogic             | -             | `4`                                                                         | Fixed number of repeated component definitions. |

### Example Manifests

#### Simple usage

```json
{
  "type": "form-repeater",
  "config": {
    "field_name": "data.agents",
    "components": [
      {
        "type": "form-input",
        "config": {
          "field_name": "data.agents.*.name",
          "content_key": {
            "label": "form.agents.name.label",
            "placeholder": "form.agents.name.placeholder"
          }
        }
      }
    ]
  }
}
```

#### Usage with all properties

When using `fixed_length` it's not recommended to use `add` and `remove` components as on every new render component will reset it's fixed length. This is good for when you need to set fixed length based on another value.

```json
{
  "type": "form-repeater",
  "config": {
    "field_name": "agents",
    "fixed_length": {
      "type": "jsonlogic",
      "schema": {
        "var": "input.data.agents_count"
      }
    },
    "components": [
      {
        "type": "form-input",
        "config": {
          "field_name": "data.agents.*.name",
          "content_key": {
            "label": "form.agents.name.label",
            "placeholder": "form.agents.name.placeholder"
          }
        }
      },
      {
        "type": "form-repeater-remove",
        "config": {
          "field_name": "data.agents.*",
          "components": [
            {
              "type": "content-line",
              "config": {
                "content_key": "form.agents.remove_item"
              }
            }
          ]
        }
      }
    ]
  }
}
```

#### Usage with only one selected item showing

You can use `select_field_name` to set name of field where index of what item to show will be controlled from. This is best used together with `form-repeater-select` component.

```json
[
  {
    "type": "form-repeater",
    "config": {
      "field_name": "data.agents",
      "select_field_name": "data.agent_index",
      "components": [
        {
          "type": "form-input",
          "config": {
            "field_name": "data.agents.*.name",
            "content_key": {
              "label": "form.agents.name.label",
              "placeholder": "form.agents.name.placeholder"
            }
          }
        },
        {
          "type": "form-repeater-remove",
          "config": {
            "field_name": "data.agents.*",
            "components": [
              {
                "type": "content-line",
                "config": {
                  "content_key": "form.agents.remove_item"
                }
              }
            ]
          }
        }
      ]
    }
  },
  {
    "type": "form-repeater-select",
    "config": {
      "field_name": "data.agent_index",
      "repeater_field_name": "data.agents",
      "direction": "previous",
      "components": [
        {
          "type": "content-line",
          "config": {
            "content_key": "form.agents.previous"
          }
        }
      ]
    }
  },
  {
    "type": "form-repeater-select",
    "config": {
      "field_name": "data.agent_index",
      "repeater_field_name": "data.agents",
      "direction": "next",
      "components": [
        {
          "type": "content-line",
          "config": {
            "content_key": "form.agents.next"
          }
        }
      ]
    }
  }
]
```

### Field definition

#### Defining and validating arrays

This is crutial as value passed in form-repeater component from input must be `array`. Therefore it must be set in field definition validation.

```json
{
  "name": "agents",
  "path": "data",
  "validation": "required|array|min:1|max:4"
}
```

#### Defining and validating array structure

It's possible to define structure for arrays writing path for array and using `*` (means any number) in place where array indexes would be. API will receive data in data structure set this way. If no data structure is set, then API will receive all data in defined array.

```json
{
  "name": "name",
  "path": "data.agents.*",
  "validation": "required|string"
}
```

#### Example of field definition together

```json
{
  "policy": [
    {
      "name": "agents",
      "path": "data",
      "validation": "required|array|min:1|max:4"
    },
    {
      "name": "name",
      "path": "data.agents.*",
      "validation": "required|string"
    }
  ]
}
```

### Prefilling data

Data can be prefilled using `default_values` in manifest configuration.

```json
{
  "default_values": {
    "data.agents": [
      {
        "name": "John Doe",
      },
      {
        "name": "John Wick",
      }
    ]
  }
}
```

### Contents

It is possible to get repeated element index in child components content strings.

```csv
"form.data.*.title","Item no. {context.repeater_index_human}"
```

To access value for dynamic index use content string like so:

```csv
"summary.agents.*.name.value","{input.data.agents[context.repeater_index].name}"
```

### Summary

Once again it's possible to use repeater in summary screen. Even if repeater uses `select_field_name`. On clicking edit button, user will automatically be switched to repeater input screen and prefill `select_field_name` with correct index.

Example:

```js
{
  "type": "summary-panel",
  "config": {
    "content_key": "flow.summary.cars.title",
    "components": [
      {
        "type": "form-repeater",
        "config": {
          "field_name": "data.cars",
          "components": [
            {
              "type": "summary-panel-row",
              "class": "summary-page",
              "config": {
                "input_field": "data.cars.*.manufacturer",
                "select_field_name": "data.selected_car",
                "content_key": {
                  "label": "flow.summary.cars.label",
                  "value": "flow.summary.cars.value"
                }
              }
            }
          ]
        }
      }
    ]
  }
}
```

In this example `selected_car` is field that contains index as integer and `cars` is array repeater field.

### Jsonlogic

It is possible to get repeated element index in child components jsonlogic too.

```js
{
  "type": "jsonlogic",
  "schema": {
    "var": "context.repeater_index"
  }
}
```

This will return number starting from "0".

Or create field name using `cat` jsonlogic operator.

```js
{
  "type": "jsonlogic",
  "schema": {
    "!!": [
      {
        "var": {
          "cat": [
            "input.data.agents.",
            {"var": "context.repeater_index"},
            ".name"
          ]
        }
      }
    ]
  }
}
```

## Form Repeater Add Component

Form Repeater add component is meant to work hand in hand with `form-repeater` component. It is a button that pushes new data to array field.

### Properties

| Property    | Required | Available values                                                         | Default Value | Example                                                                | Description                                             |
| ----------- | -------- | ------------------------------------------------------------------------ | ------------- | ---------------------------------------------------------------------- | ------------------------------------------------------- |
| field\_name | yes      | `string`                                                                 | -             | `"item_description"`                                                   | Name of the array field.                                |
| components  | yes      | `array` of component definitions.                                        | -             | `[{"type":"content-line", {"config": {"content_key": "agents.add"}}}]` | Content of button.                                      |
| defaults    | no       | `object`                                                                 | `{}`          | `{"first_name": "", "last_name": ""}`                                  | Data that will be added to array when button is licked. |
| color       | no       | `"primary"`, `"info"`, `"default"`, `"success"`, `"warning"`, `"danger"` | `"info"`      | `"success"`                                                            | Color of the button.                                    |

### Example Manifests

#### Simple usage

```json
{
  "type": "form-repeater-add",
  "config": {
    "field_name": "data.agents",
    "components": [
      {
        "type": "content-line",
        "config": {
          "content_key": "form.agents.add_item"
        }
      }
    ]
  }
}
```

## Form Repeater Remove Component

Form Repeater Remove component is meant to work hand in hand with `form-repeater` component and must be placed inside `form-repeater` components. It is a button that removes data from array field by index.

### Properties

| Property    | Required | Available values                                                         | Default Value | Example                                                                   | Description              |
| ----------- | -------- | ------------------------------------------------------------------------ | ------------- | ------------------------------------------------------------------------- | ------------------------ |
| field\_name | yes      | `string`                                                                 | -             | `"data.agents.*"`                                                         | Name of the array field. |
| components  | yes      | `array` of component definitions.                                        | -             | `[{"type":"content-line", {"config": {"content_key": "agents.remove"}}}]` | Content of button.       |
| color       | no       | `"primary"`, `"info"`, `"default"`, `"success"`, `"warning"`, `"danger"` | `"info"`      | `"danger"`                                                                | Color of the button.     |

### Example Manifests

#### Simple usage

```json
{
  "type": "form-repeater-remove",
  "config": {
    "field_name": "data.agents.*",
    "components": [
      {
        "type": "content-line",
        "config": {
          "content_key": "form.agents.remove_item"
        }
      }
    ]
  }
}
```

## Form Repeater Select Component

Form Repeater select component is meant to work hand in hand with `form-repeater` component. It is a button that selects item to show in repeater component.

### Properties

| Property              | Required | Available values                                                         | Default Value | Example                                                                  | Description                         |
| --------------------- | -------- | ------------------------------------------------------------------------ | ------------- | ------------------------------------------------------------------------ | ----------------------------------- |
| field\_name           | yes      | `string`                                                                 | -             | `"data.agent_index"`                                                     | Name of the index field.            |
| repeater\_field\_name | yes      | `string`                                                                 | -             | `"data.agents"`                                                          | Name of the repeater array field.   |
| components            | yes      | `array` of component definitions.                                        | -             | `[{"type":"content-line", {"config": {"content_key": "agents.right"}}}]` | Content of button.                  |
| direction             | no       | `"next", "previous"`                                                     | `"next"`      | `"previous"`                                                             | Direction that user should be sent. |
| color                 | no       | `"primary"`, `"info"`, `"default"`, `"success"`, `"warning"`, `"danger"` | `"info"`      | `"success"`                                                              | Color of the button.                |
| disabled              | no       | `boolean` or `jsonlogic`                                                 | `false`       | `true`                                                                   | The button is disabled.             |

### Example Manifests

#### Simple usage

```json
{
  "type": "form-repeater-select",
  "config": {
    "field_name": "data.agent_index",
    "repeater_field_name": "data.agents",
    "direction": "next",
    "components": [
      {
        "type": "content-line",
        "config": {
          "content_key": "form.agents.right"
        }
      }
    ]
  }
}
```

#### Usage with all properties

```json
{
  "type": "form-repeater-select",
  "config": {
    "field_name": "data.agent_index",
    "repeater_field_name": "data.agents",
    "direction": "previous",
    "components": [
      {
        "type": "icon",
        "config": {
          "type": "fa",
          "content": "fa-angle-left"
        }
      }
    ],
    "color": "success",
    "disabled": {
      "type": "jsonlogic",
      "schema": {
        "if": true
      }
    }
  }
}
```
