# Form layout customization

{% hint style="success" %}
This is the official documentation of the `agent_ruby` Ruby agent.
{% endhint %}

## Form layout

The form layout feature lets you organize your fields in pages or rows, and add separators or html blocks. This is especially useful if you have many fields to display, and you want to break down your action form into more manageable chunks !

Theses form elements are available since the version `1.0.0` of the agent.

## Layout items

| Name                              | Nested elements                          | Description                                                                                                                                                                                                        |
| --------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [Separator](#separator-element)   | None                                     | Allow to add a horizontal separator between two form elements                                                                                                                                                      |
| [HTML block](#html-block-element) | None                                     | Allow to show HTML content                                                                                                                                                                                         |
| [Row](#row-element)               | Fields                                   | Allow to put two (and only two) fields (and not layout elements) in a row                                                                                                                                          |
| [Page](#multi-pages-form)         | Fields & layouts elements (but no pages) | <p>Allow to use multi pages forms.<br><span data-gb-custom-inline data-tag="emoji" data-code="26a0">⚠️</span> When using multi pages form, you <strong>must have only</strong> pages at the root of your form.</p> |

### General properties

Some layouts items will have options, but here are the common properties to all the layout elements

| Name          | Usage        | Expected value                                                                                                                        | Description                                                                                                                                                                                                                           |
| ------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type          | **required** | `Layout`                                                                                                                              | It differentiate a `field` from `layout` elements. See over values in [static form documentation](https://docs.forestadmin.com/developer-guide-agents-ruby/agent-customization/forms-static#properties)                               |
| component     | **required** | `Separator`, `Row`, `HtmlBlock`, or `Page`                                                                                            | The layout component                                                                                                                                                                                                                  |
| if\_condition | optional     | callable with [context](https://docs.forestadmin.com/developer-guide-agents-ruby/agent-customization/actions/scope-context) parameter | Only display the field if the function returns true. This one is the exact same one as presented in [dynamic forms](https://docs.forestadmin.com/developer-guide-agents-ruby/agent-customization/forms-dynamic#form-field-properties) |

## Separator element

| Name      | Usage        | Expected value | Description              |
| --------- | ------------ | -------------- | ------------------------ |
| component | **required** | "Separator"    | To enable this component |

This item doesn't have specific options.

Example:

```ruby
include ForestAdmin::Types

@create_agent.customize_collection('customer') do |collection|
  collection.add_action(
    'What\'s your name',
    BaseAction.new(
      scope: ActionScope::SINGLE,
      form: [
        {
          type: FieldType::STRING,
          label: 'firstName',
        }
        {
          type: FieldType::LAYOUT,
          component: 'Separator',
        }
        {
          type: FieldType::STRING,
          label: 'lastName',
        }
      ]
    ) do |context, result_builder|
      result_builder.success()
    end
  )
end

```

![Example](https://561307319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fn23xpsrpC8uJXljJ3an2%2Fuploads%2Fgit-blob-c335ca23cd6abae5fb2c705e5527ec1c160e4ade%2Faction-form-layout-separator.png?alt=media)

## HTML Block element

| Name      | Usage        | Expected value                                                                                                                                                                        | Description                      |
| --------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| component | **required** | "HtmlBlock"                                                                                                                                                                           | To enable this component         |
| content   | **required** | String or callable with [context](https://docs.forestadmin.com/developer-guide-agents-ruby/agent-customization/actions/scope-context) parameter, returning a string formatted as html | This is the HTML content to show |

Example:

```ruby
include ForestAdmin::Types

@create_agent.customize_collection('customer') do |collection|
  collection.add_action(
    'Boring form',
    BaseAction.new(
      scope: ActionScope::GLOBAL,
      form: [
        {
            type: FieldType::STRING,
            label: "firstName",
            default_value: ->(context) { context.caller.first_name },
        },
        {
            type: FieldType::STRING,
            label: "lastName",
            default_value: ->(context) { context.caller.last_name },
        },
        {
            type: FieldType::LAYOUT,
            component: 'HtmlBlock',
            content: ->(context) {
'<div style="text-align:center;">
    <p>
        <strong>Hi #{ctx.form_values["firstName"]} #{ctx.form_values["lastName"]}</strong>,
        <br/>here you can put
        <strong style="color: red;">all the html</strong> you want.
    </p>
</div>
<div style="display: flex; flex-flow: row wrap; justify-content: space-around;">
    <a href="https://www.w3schools.com" target="_blank">
        <img src="https://www.w3schools.com/html/w3schools.jpg">
    </a>
    <iframe src="https://www.youtube.com/embed/xHPKuu9-yyw?autoplay=1&mute=1"></iframe>
</div>,
'
            },
        }
        # ...
      ]
    ) do |context, result_builder|
      result_builder.success()
    end
  )
end

```

![Example](https://561307319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fn23xpsrpC8uJXljJ3an2%2Fuploads%2Fgit-blob-b6d7856ee267a244ec5e293ee4f234292c7412ff%2Faction-form-layout-htmlblock.png?alt=media)

## Row element

:warning: **This element is designed to work with only two inner fields.** You can control the display of each field using the `if_condition` property. If only one field is displayed, it will occupy the entire line. However, if the conditions defined by the `if_condition` properties result in more than two fields being displayed, only the first two will be shown. If there is nothing inside, it will be removed.

| Name      | Usage        | Expected value                                                                                                                       | Description                                                                                                                                                                                                               |
| --------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| component | **required** | "Row"                                                                                                                                | To enable this component                                                                                                                                                                                                  |
| fields    | **required** | Array of two [fields](https://docs.forestadmin.com/developer-guide-agents-ruby/agent-customization/forms-static#field-configuration) | <p>These two fields are the ones you want to display in a line<br><span data-gb-custom-inline data-tag="emoji" data-code="26a0">⚠️</span> No layout elements are allowed in a <code>Row</code> component; only fields</p> |

Example:

```ruby
include ForestAdmin::Types

@create_agent.customize_collection('customer') do |collection|
  collection.add_action(
    'Personal form',
    BaseAction.new(
      scope: ActionScope::GLOBAL,
      form: [
        # ...
        {
            type: FieldType::LAYOUT,
            component: 'Row',
            fields: [
                {
                    label: 'gender',
                    type: FieldType::ENUM,
                    enum_values: ['M', 'F', 'other'],
                },
                {
                    label: 'specify',
                    description: 'you may specify here'
                    type: FieldType::STRING,
                    if_condition: ->(context) { context.form_values['gender'] == 'other' },
                },
            ]
        },
        # ...
      ]
    ) do |context, result_builder|
      result_builder.success()
    end
  )
end

```

![Example](https://561307319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fn23xpsrpC8uJXljJ3an2%2Fuploads%2Fgit-blob-af6dc1ed220f53dc9567d76822d1f05a857598a4%2Faction-form-layout-row.png?alt=media)

## Multi pages form

### Description

The pages feature is a way to break up your action form into more manageable chunks, by showing only a subset of fields at the same time, and letting the user navigate between the pages.

### Limitations

Please note this list of limitations:

* You cannot mix fields and pages at the root of your form, or put nest a page in a page
* The next (or previous) button is not clickable on the last (or first) page
* If you're using if conditions in a page; keep in mind that **if** all the elements in your page are hidden, the page will automatically be removed. You can avoid this by behavior by adding an unconditional [htmlBlock](#html-block-element) inside your page explaining why is your page empty.

| Name                    | Usage        | Expected value                      | Description                                                                                                                                                                                      |
| ----------------------- | ------------ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| component               | **required** | "Page"                              | To enable this component                                                                                                                                                                         |
| elements                | **required** | Array of fields and layout elements | The layout elements defined in this page and the fields defined [in the others documentation](https://docs.forestadmin.com/developer-guide-agents-ruby/agent-customization/actions/forms-static) |
| next\_button\_label     | optional     | String                              | The label on the `next` button                                                                                                                                                                   |
| previous\_button\_label | optional     | String                              | The label on the `previous` button                                                                                                                                                               |

Example:

```ruby
include ForestAdmin::Types

@create_agent.customize_collection('customer') do |collection|
  collection.add_action(
    'Create user with address',
    BaseAction.new(
      scope: ActionScope::GLOBAL,
      form: [
        {
            type: FieldType::LAYOUT,
            component: "Page",
            next_button_label: 'Go to address',
            elements: [
                {type: FieldType::STRING, id: "Firstname", label: "First name"},
                {type: FieldType::STRING, id: "Lastname", label: "Last name"},
                {type: FieldType::LAYOUT, component: "Separator"},
                {type: FieldType::DATE, id: "Birthdate", label: "Birth date"},
            ],
        },
        {
            type: FieldType::LAYOUT,
            component: "Page",
            previous_button_label: "Go back to identity",
            elements: [
                {
                    type: FieldType::LAYOUT,
                    component: "Row",
                    fields: [
                        {type: FieldType::NUMBER, label: "StreetNumber"},
                        {type: FieldType::STRING, label: "StreetName"},
                    ],
                },
                {type: FieldType::LAYOUT, component: "Separator"},
                {type: FieldType::STRING, id: "PostalCode", label: "Postal code"},
                {type: FieldType::STRING, label: "City"},
                {type: FieldType::LAYOUT, component: "Separator"},
                {type: FieldType::STRING, label: "Country"},
            ],
        },
      ]
    ) do |context, result_builder|
      result_builder.success()
    end
  )
end

```

![page 1](https://561307319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fn23xpsrpC8uJXljJ3an2%2Fuploads%2Fgit-blob-99232eda14e742ee151113533fe59e4349497f4e%2Faction-form-layout-pages-1.png?alt=media) ![page 2](https://561307319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fn23xpsrpC8uJXljJ3an2%2Fuploads%2Fgit-blob-9b409b1907f4776065a84b77dc23a0f25efcac27%2Faction-form-layout-pages-2.png?alt=media)
