Skip to content

KeyValue Field ​

The KeyValue field type allows users to create and manage a dynamic list of key-value pairs, or dictionary entries, within the CMS entry form.

User Interface ​

Editor ​

A dynamic list of key-value pairs, where users can add, edit, reorder and remove entries. Each entry consists of a text input for the key and a text input for the value.

  • Pressing Enter moves focus or adds a new row while editing.
  • Each pair can be reordered using the drag handle at the start of its row, with the same pointer, keyboard and touch screen behavior as the List field. The pairs are saved in the order they are shown.
  • A field without pairs shows a blank row, like a simple List field, so there’s always somewhere to type. The blank row isn’t saved until its key is filled in, and removing the last pair leaves one in its place.

Preview ​

A table displaying the current key-value pairs in a structured format for easy review.

Data Type ​

An object where each key corresponds to a user-defined key and each value corresponds to the associated value.

If the required option is set to false and the field is left empty, the value will be an empty object.

Data Validation ​

  • If the required option is set to true, at least one key-value pair must be present. A blank pair, with neither a key nor a value, doesn’t count.
  • Keys must be unique and non-empty strings. Keys cannot contain dots (.) as they may interfere with nested data structures.
  • If min and/or max options are specified, the number of key-value pairs must be within the defined limits.

Options ​

In addition to the common field options, the KeyValue field supports the following options:

Required Options ​

widget ​

  • Type: string
  • Default: string

Must be set to keyvalue.

Optional Options ​

default ​

  • Type: object
  • Default: {}

The default value for the field when creating a new entry.

key_label ​

  • Type: string
  • Default: "Key" or its localized equivalent

The label for the key input field.

value_label ​

  • Type: string
  • Default: "Value" or its localized equivalent

The label for the value input field.

label_singular ​

  • Type: string
  • Default: The value of the label option

A label used for a single key-value pair, e.g., “Setting” for a field labeled “Settings”. It will be displayed on the Add button, just like the label_singular option for the List field.

min ​

  • Type: integer
  • Default: 0

The minimum number of key-value pairs required. This enables validation to ensure that users add at least this many entries.

max ​

  • Type: integer
  • Default: Infinity

The maximum number of key-value pairs allowed. This enables validation to prevent users from adding more than this many entries.

root ​

  • Type: boolean
  • Default: false

If set to true, the key-value pairs will be stored at the root level of the entry data instead of nested under the field name. This is similar to how the root option for the List field works. The option is ignored unless the field is the only field in the collection or file.

See the Top-Level key-value pairs example below for details.

i18n ​

  • Type: boolean, duplicate or duplicate_keys
  • Default: false

In addition to the common i18n option values, the KeyValue field accepts the duplicate_keys value, which is useful for dictionaries whose keys are shared across locales while their values are translated:

  • The keys are copied from the default locale to the other locales, where they are read-only. Keys can only be added, renamed or removed in the default locale, and any such change is immediately reflected in the other locales.
  • The values can be edited separately for each locale. When a key is renamed in the default locale, the other locales keep the value they had under the old name; a newly added key starts with an empty value in the other locales.
  • The order of the keys follows the default locale as well: reordering the pairs there reorders them in the other locales, which keep their own values.

See the Translated Values with Shared Keys example below for details.

Examples ​

Basic Key-Value Field ​

This example demonstrates a simple KeyValue field configuration:

yaml
- name: settings
  label: Settings
  widget: keyvalue
toml
[[fields]]
name = "settings"
label = "Settings"
widget = "keyvalue"
json
{
  "name": "settings",
  "label": "Settings",
  "widget": "keyvalue"
}
js
{
  name: 'settings',
  label: 'Settings',
  widget: 'keyvalue',
}

Output example:

yaml
settings:
  theme: dark
  notifications: enabled
toml
[settings]
theme = "dark"
notifications = "enabled"
json
{
  "settings": {
    "theme": "dark",
    "notifications": "enabled"
  }
}

Translated Values with Shared Keys ​

This example demonstrates how to use the duplicate_keys i18n strategy so that the same keys are used in all locales while the values are translated. This requires i18n to be enabled for the collection:

yaml
- name: labels
  label: Labels
  widget: keyvalue
  i18n: duplicate_keys
toml
[[fields]]
name = "labels"
label = "Labels"
widget = "keyvalue"
i18n = "duplicate_keys"
json
{
  "name": "labels",
  "label": "Labels",
  "widget": "keyvalue",
  "i18n": "duplicate_keys"
}
js
{
  name: 'labels',
  label: 'Labels',
  widget: 'keyvalue',
  i18n: 'duplicate_keys',
}

Output example, with English as the default locale and the single_file i18n structure:

yaml
en:
  labels:
    submit: Submit
    cancel: Cancel
ja:
  labels:
    submit: 送信
    cancel: キャンセル
toml
[en.labels]
submit = "Submit"
cancel = "Cancel"

[ja.labels]
submit = "送信"
cancel = "キャンセル"
json
{
  "en": {
    "labels": {
      "submit": "Submit",
      "cancel": "Cancel"
    }
  },
  "ja": {
    "labels": {
      "submit": "送信",
      "cancel": "キャンセル"
    }
  }
}

Top-Level Key-Value Pairs ​

This example demonstrates how to use the root option to store key-value pairs at the root level of the entry data:

yaml
- name: settings
  label: Settings
  widget: keyvalue
  root: true
toml
[[fields]]
name = "settings"
label = "Settings"
widget = "keyvalue"
root = true
json
{
  "name": "settings",
  "label": "Settings",
  "widget": "keyvalue",
  "root": true
}
js
{
  name: 'settings',
  label: 'Settings',
  widget: 'keyvalue',
  root: true,
}

Output example:

yaml
theme: dark
notifications: enabled
toml
theme = "dark"
notifications = "enabled"
json
{
  "theme": "dark",
  "notifications": "enabled"
}