Skip to content

array

An array field has its own field schema and allows the user to add one or more entries that use the fields in that schema. The overall field is stored in the database as an array of an object for each entry.

This is useful for collections of structured data that clearly belong to a parent document but won't have relationships to other documents, such as multiple sets of contact information for business locations or tabs in a widget.

See the relationship field if you exclusively, or primarily, need to identify a series of other pieces or pages.

Module field definition

javascript
// Configuring the `contactInfo` array field in a module's `fields.add` subsection:
contactInfo: {
  label: 'Contact information',
  type: 'array',
  titleField: 'city',
  fields: {
    add: {
      city: {
        type: 'string',
        label: 'City'
      },
      email: {
        type: 'email',
        label: 'Email address'
      }
    }
  }
}

Settings

Required

PropertyTypeDefaultDescription
labelStringn/aSets the visible label for the field in the UI
typeStringn/aSpecifies the field type (array for this type)
fieldsObjectn/aThe field schema for the array items. See below.

Optional

PropertyTypeDefaultDescription
defArrayn/aThe default value for the field. It must comply with the array fields schema.
helpStringn/aHelp text for the content editor
htmlHelpStringn/aHelp text with support for HTML markup
ifObject{}Conditions to meet before the field is active. See the guide for details.
requiredIfObject{}Conditions to meet before the field is required. See the guide for details.
hiddenBooleanfalseIf true, the field is hidden
inlineBooleanfalseIf true, array fields are edited inline with others, not in a separate dialog box.
duplicateBooleantrueOnly applied to inline arrays. If true, array element's context menu has a Duplicate action
styleStringn/aOnly if inline is true. If set to table, the schema will be displayed as an HTML table
minIntegern/aThe minimum number of entries required in the array
maxIntegern/aThe maximum number of entries allowed in the array
requiredBooleanfalseIf true, the field is mandatory
readOnlyBooleanfalseIf true, prevents the user from editing the field value
titleFieldStringn/aThe name of one of the array schema fields. If provided, the user interface will use the value of that field as a label for the array tabs.
draggableBooleantrueIf false, array items cannot be reordered using drag and drop feature.
whenEmptyObjectYesProvide a custom label and icon to be displayed if an array is empty.

NOTE

  • If there is no titleField value, the items are numbered.
  • Setting titleField is recommended to improve clarity for content editors.
  • titleField can access relationship sub-field documents by using dot notation (e.g., _team[0].mascot).

inline

Set inline: true on an array field to edit the array inline with the rest of the fields, rather than in a separate dialog box. This works best with a small number of fields in the array.

Care should be taken when using style: table along with conditional fields. In general, conditional fields should "switch" between two fields that have the same label in order to maintain the table structure. For example:

javascript
...
  inlineArrayTableField: {
    label: 'Dessert Table',
    itemLabel: 'Dessert Item',
    type: 'array',
    inline: true,
    style: 'table',
    fields: {
    add: {
      brand: {
        type: 'string',
        label: 'Brand',
        required: true
      },
      dessertType: {
        type: 'select',
        label: 'Dessert Type',
        choices: [
          {
            label: 'Ice Cream',
            value: 'iceCream'
          },
          {
            label: 'Sorbet',
            value: 'sorbet'
          }
        ],
        def: 'iceCream'
      },
      iceCream: {
        type: 'select',
        label: 'Flavor',
        choices: [
          {
            label: 'Cherry',
            value: 'cherry'
          },
          {
            label: 'Raspberry',
            value: 'raspberry'
          }
        ],
        if: {
          dessertType: 'iceCream'
        },
        def: 'cherry',
        required: true
      },
      sorbet: {
        type: 'select',
        label: 'Flavor',
        choices: [
          {
            label: 'Orange',
            value: 'orange'
          },
          {
            label: 'Ginger',
            value: 'ginger'
          }
        ],
        if: {
          dessertType: 'sorbet'
        },
        def: 'orange',
        required: true
      }
    }
  }
}
...

In this example, the third field will "switch" between the ice cream flavors and the sorbet flavors. Not that the label, Flavor, is the same for both fields. This means that the label at the top of the table will not change if one item in the array selects ice cream and another selects sorbet.

whenEmpty

If no array items have been added and the array has inline: true, the whenEmpty setting supplies an object consisting of a label and icon that are displayed to the editor until items are added. The label property takes a localizable string, while the icon property takes an icon that has already been registered or is registered through a module icons property.

javascript
{
  whenEmpty: {
    label: 'apostrophe:whemEmpty',
    icon: 'file-document-icon'
  }
}

Configuring the array field schema

Array field schemas are generally configured the same way as the module's overall field schema is configured. The module's schema is configured in its fields section's add subsection. Similarly, array field schema are configured in a fields property, using its add subproperty to configure the actual fields. Both use the field names as keys in the add object. Both can contain all field types, including nested array fields.

Array schema configuration differs from module schema configuration in that array schemas do not use group or remove settings.

Use in templates

Nunjucks provides the {% for %} template tag to loop over arrays. This is the most common way to traverse the array field data and sub-fields.

nunjucks
<ul>
{% for contact in data.piece.contactInfo %}
  <li>{{ contact.city }}: {{ contact.email }}</li>
{% endfor %}
</ul>