List Field
The List field type allows users to create and manage lists of items within the CMS entry form. It supports various configurations for defining the structure and type of items in the list, either as a simple array or as a list of complex objects.
User Interface
Editor
The List field type has four different UI modes, depending on the configuration:
- Complex list field:
- With the
fieldoption: A single subfield editor is shown for each item in the list. - With the
fieldsoption: A group of subfield editors is shown for each item in the list. - With the
typesoption: A type selector is shown for each item, along with the corresponding subfield editors. This configuration is called a variable type list. It’s useful for creating flexible content structures like page builders.
- With the
- Simple list field:
- Without the
field,fieldsortypesoption: A simple multiline text area is shown for editing string values. This allows users to enter list items separated by new lines, where spaces and commas are treated as part of the item values instead of delimiters.
- Without the
With a complex list field:
- Each item in the list can be expanded or collapsed to show or hide its subfields.
- Each item comes with a menu that allows users to duplicate the item, insert a new item above/below it, or remove it.
- Users can expand or collapse the entire list using the Expand All and Collapse All buttons.
Future Plans
The UI will be improved in the future to support additional features like drag-and-drop reordering, inline editing, and better handling of large lists.
Preview
A list view displaying all items in the list. For complex list fields, grouped subfield values are shown for each item. For simple list fields, a bulleted list of string values is displayed.
Data Type
An array. The elements can be strings or objects, depending on the configuration.
If the required option is set to false and the field is left empty, the value will be an empty array.
Data Validation
- If the
requiredoption is set totrue, the list must contain at least one item. - If the
minand/ormaxoptions are specified, the number of items in the list must be within the defined limits. - Each item in the list is validated according to the subfield definitions, if applicable.
Options
In addition to the common field options, the List field supports the following options:
Required Options
widget
- Type:
string - Default:
string
Must be set to list to use the List field type.
General Options
default
Subfield Definition
These options are mutually exclusive; you can only use one of them at a time:
field
- Type: A single field definition
fields
- Type:
arrayof field definitions
types
- Type:
arrayof variable type definitions
Each type definition is an object with the following properties:
name(string, required): The unique identifier for the type.label(string, required): The display label for the type.widget(string, optional): The field type for this type. It must beobjectif not omitted. Other field types are invalid.fields(array of field definitions, optional): The subfields for this type.
Subfield Options
These options are effective only when the field, fields, or types option is used:
root
- Type:
boolean - Default:
false
Whether to store the list at the root level of the output file, without a parent key. This is useful for creating top-level lists in files.
The root option is ignored in the following cases:
- The file or singleton contains multiple fields. You can still have subfields under the List field.
- The file format is TOML, because TOML doesn’t support top-level arrays.
See the Top-Level List example below for details.
label_singular
- Type:
string - Default: The value of the
labeloption
A label used for singular items in the list, e.g., "Member" for a list labeled "Members". It will be displayed on the Add button and in other relevant places in the UI.
summary
- Type:
string - Default:
""
A template string used to generate a summary for each item in the collapsed view. It can include subfield values using the {{subfield_name}} syntax. String transformations can be applied in this option. If omitted, the summary will be automatically generated based on the first textual subfield found.
See the Using Summary and Thumbnail example below for details.
thumbnail
- Type:
string - Default:
""
An Image subfield name to be used as the thumbnail for each list item in the collapsed view, if applicable. If omitted, no thumbnail will be displayed.
See the Using Summary and Thumbnail example below for details.
collapsed
- Type:
booleanorauto - Default:
false
Whether each item is initially collapsed in the UI. If set to auto, the UI is collapsed if an item has any filled subfields and expanded if all the subfields are empty.
minimize_collapsed
- Type:
booleanorauto - Default:
false
Whether the entire list is minimized when collapsed. If set to auto, the list is minimized if any item has any filled subfields and expanded if all items are empty.
allow_add
- Type:
boolean - Default:
true
Whether to allow adding new items to the list. If set to false, the Add button will be hidden.
allow_remove
- Type:
boolean - Default:
true
Whether to allow removing items from the list. If set to false, the Remove button will be hidden.
allow_reorder
- Type:
boolean - Default:
true
Whether to allow reordering of items in the list with an arrow handle or drag-and-drop. If set to false, the reorder handles will be hidden.
min
- Type:
integer - Default:
0
The minimum number of items required in the list. If the number of items is below this value, a validation error will be shown.
max
- Type:
integer - Default:
Infinity
The maximum number of items allowed in the list. If the number of items exceeds this value, a validation error will be shown.
add_to_top
- Type:
boolean - Default:
false
Whether to add new items to the top of the list instead of the bottom. If set to true, the Add button will appear at the top of the list.
typeKey
- Type:
string - Default:
type
This option is effective only when the types option is used. It allows you to customize the name of the field that indicates the type of each item in the list. See the Variable Type example below for details.
You cannot use a key that conflicts with any of the subfield names defined in the object.
TIP
Unlike most of other config options, typeKey is camelCased.
Examples
Simple List
Configuration example:
- name: tags
label: Tags
widget: list[[fields]]
name = "tags"
label = "Tags"
widget = "list"{
"name": "tags",
"label": "Tags",
"widget": "list"
}{
name: "tags",
label: "Tags",
widget: "list",
}Output example:
tags:
- travel
- photography
- foodtags = ["travel", "photography", "food"]{
"tags": ["travel", "photography", "food"]
}Single Subfield
Configuration example:
- name: authors
label: Authors
widget: list
field:
name: author
label: Author
widget: string[[fields]]
name = "authors"
label = "Authors"
widget = "list"
[field]
name = "author"
label = "Author"
widget = "string"{
"name": "authors",
"label": "Authors",
"widget": "list",
"field": {
"name": "author",
"label": "Author",
"widget": "string"
}
}{
name: "authors",
label: "Authors",
widget: "list",
field: {
name: "author",
label: "Author",
widget: "string",
},
}Output example:
authors:
- Alice
- Bob
- Charlieauthors = ["Alice", "Bob", "Charlie"]{
"authors": ["Alice", "Bob", "Charlie"]
}Note that the name of the subfield will not appear in the output; only the values will be included in the list, just like a simple list.
Multiple Subfields
Configuration example:
- name: team_members
label: Team Members
widget: list
fields:
- name: name
label: Name
widget: string
- name: role
label: Role
widget: string[[fields]]
name = "team_members"
label = "Team Members"
widget = "list"
[[fields.fields]]
name = "name"
label = "Name"
widget = "string"
[[fields.fields]]
name = "role"
label = "Role"
widget = "string"{
"name": "team_members",
"label": "Team Members",
"widget": "list",
"fields": [
{
"name": "name",
"label": "Name",
"widget": "string"
},
{
"name": "role",
"label": "Role",
"widget": "string"
}
]
}{
name: "team_members",
label: "Team Members",
widget: "list",
fields: [
{
name: "name",
label: "Name",
widget: "string",
},
{
name: "role",
label: "Role",
widget: "string",
},
],
}Output example:
team_members:
- name: Alice
role: Developer
- name: Bob
role: Designer
- name: Charlie
role: Product Manager[[team_members]]
name = "Alice"
role = "Developer"
[[team_members]]
name = "Bob"
role = "Designer"
[[team_members]]
name = "Charlie"
role = "Product Manager"{
"team_members": [
{
"name": "Alice",
"role": "Developer"
},
{
"name": "Bob",
"role": "Designer"
},
{
"name": "Charlie",
"role": "Product Manager"
}
]
}Using Summary and Thumbnail
Configuration example:
- name: projects
label: Projects
widget: list
summary: "{{name}} - {{status}}"
thumbnail: "image"
fields:
- name: name
label: Name
widget: string
- name: status
label: Status
widget: string
- name: image
label: Image
widget: image[[fields]]
name = "projects"
label = "Projects"
widget = "list"
summary = "{{name}} - {{status}}"
thumbnail = "image"
[[fields.fields]]
name = "name"
label = "Name"
widget = "string"
[[fields.fields]]
name = "status"
label = "Status"
widget = "string"
[[fields.fields]]
name = "image"
label = "Image"
widget = "image"{
"name": "projects",
"label": "Projects",
"widget": "list",
"summary": "{{name}} - {{status}}",
"thumbnail": "image",
"fields": [
{
"name": "name",
"label": "Name",
"widget": "string"
},
{
"name": "status",
"label": "Status",
"widget": "string"
},
{
"name": "image",
"label": "Image",
"widget": "image"
}
]
}{
name: "projects",
label: "Projects",
widget: "list",
summary: "{{name}} - {{status}}",
thumbnail: "image",
fields: [
{
name: "name",
label: "Name",
widget: "string",
},
{
name: "status",
label: "Status",
widget: "string",
},
{
name: "image",
label: "Image",
widget: "image",
},
],
}Variable Type
The following example defines a variable type List field named items with two types: text_item and image_item. User can add either type of item to the list. These types can be mixed in any order.
- name: items
label: Items
widget: list
types:
- name: text_item
label: Text Item
fields:
- name: text
label: Text
widget: string
- name: image_item
label: Image Item
fields:
- name: url
label: Image URL
widget: image
- name: caption
label: Caption
widget: string[[fields]]
name = "items"
label = "Items"
widget = "list"
[[fields.types]]
label = "Text Item"
name = "text_item"
[[fields.types.fields]]
name = "text"
label = "Text"
widget = "string"
[[fields.types]]
label = "Image Item"
name = "image_item"
[[fields.types.fields]]
name = "url"
label = "Image URL"
widget = "image"
[[fields.types.fields]]
name = "caption"
label = "Caption"
widget = "string"{
"name": "items",
"label": "Items",
"widget": "list",
"types": [
{
"label": "Text Item",
"name": "text_item",
"fields": [
{
"name": "text",
"label": "Text",
"widget": "string"
}
]
},
{
"label": "Image Item",
"name": "image_item",
"fields": [
{
"name": "url",
"label": "Image URL",
"widget": "image"
},
{
"name": "caption",
"label": "Caption",
"widget": "string"
}
]
}
]
}{
name: "items",
label: "Items",
widget: "list",
types: [
{
label: "Text Item",
name: "text_item",
fields: [
{
name: "text",
label: "Text",
widget: "string",
},
],
},
{
label: "Image Item",
name: "image_item",
fields: [
{
name: "url",
label: "Image URL",
widget: "image",
},
{
name: "caption",
label: "Caption",
widget: "string",
},
],
},
],
}Output example:
items:
- type: text_item
text: This is a text item.
- type: image_item
url: https://example.com/image.jpg
caption: An example image.
- type: text_item
text: Another text item.[[items]]
type = "text_item"
text = "This is a text item."
[[items]]
type = "image_item"
url = "https://example.com/image.jpg"
caption = "An example image."
[[items]]
type = "text_item"
text = "Another text item."{
"items": [
{
"type": "text_item",
"text": "This is a text item."
},
{
"type": "image_item",
"url": "https://example.com/image.jpg",
"caption": "An example image."
},
{
"type": "text_item",
"text": "Another text item."
}
]
}Variable Type with Nested List
The following example defines a variable type List field named sections with two types: text_section and image_gallery. The image_gallery type contains a nested List field for multiple images.
TIP
You cannot have a List field directly under the types option; it must be nested within a type Object field, as shown in this example.
- name: sections
label: Sections
widget: list
types:
- name: text_section
label: Text Section
fields:
- name: heading
label: Heading
widget: string
- name: body
label: Body
widget: text
- name: image_gallery
label: Image Gallery
fields:
- name: title
label: Title
widget: string
- name: images
label: Images
widget: list
fields:
- name: src
label: Image URL
widget: image
- name: alt
label: Alt Text
widget: string[[fields]]
name = "sections"
label = "Sections"
widget = "list"
[[fields.types]]
name = "text_section"
label = "Text Section"
[[fields.types.fields]]
name = "heading"
label = "Heading"
widget = "string"
[[fields.types.fields]]
name = "body"
label = "Body"
widget = "text"
[[fields.types]]
name = "image_gallery"
label = "Image Gallery"
[[fields.types.fields]]
name = "title"
label = "Title"
widget = "string"
[[fields.types.fields]]
name = "images"
label = "Images"
widget = "list"
[[fields.types.fields.fields]]
name = "src"
label = "Image URL"
widget = "image"
[[fields.types.fields.fields]]
name = "alt"
label = "Alt Text"
widget = "string"{
"name": "sections",
"label": "Sections",
"widget": "list",
"types": [
{
"name": "text_section",
"label": "Text Section",
"fields": [
{
"name": "heading",
"label": "Heading",
"widget": "string"
},
{
"name": "body",
"label": "Body",
"widget": "text"
}
]
},
{
"name": "image_gallery",
"label": "Image Gallery",
"fields": [
{
"name": "title",
"label": "Title",
"widget": "string"
},
{
"name": "images",
"label": "Images",
"widget": "list",
"fields": [
{
"name": "src",
"label": "Image URL",
"widget": "image"
},
{
"name": "alt",
"label": "Alt Text",
"widget": "string"
}
]
}
]
}
]
}{
name: "sections",
label: "Sections",
widget: "list",
types: [
{
name: "text_section",
label: "Text Section",
fields: [
{
name: "heading",
label: "Heading",
widget: "string",
},
{
name: "body",
label: "Body",
widget: "text",
},
],
},
{
name: "image_gallery",
label: "Image Gallery",
fields: [
{
name: "title",
label: "Title",
widget: "string",
},
{
name: "images",
label: "Images",
widget: "list",
fields: [
{
name: "src",
label: "Image URL",
widget: "image",
},
{
name: "alt",
label: "Alt Text",
widget: "string",
},
],
},
],
},
],
}Output example:
sections:
- type: text_section
heading: Welcome to Our Site
body: This is the first section of our site.
- type: image_gallery
title: Our Gallery
images:
- src: https://example.com/image1.jpg
alt: Image 1
- src: https://example.com/image2.jpg
alt: Image 2[[sections]]
type = "text_section"
heading = "Welcome to Our Site"
body = "This is the first section of our site."
[[sections]]
type = "image_gallery"
title = "Our Gallery"
[[sections.images]]
src = "https://example.com/image1.jpg"
alt = "Image 1"
[[sections.images]]
src = "https://example.com/image2.jpg"
alt = "Image 2"{
"sections": [
{
"type": "text_section",
"heading": "Welcome to Our Site",
"body": "This is the first section of our site."
},
{
"type": "image_gallery",
"title": "Our Gallery",
"images": [
{
"src": "https://example.com/image1.jpg",
"alt": "Image 1"
},
{
"src": "https://example.com/image2.jpg",
"alt": "Image 2"
}
]
}
]
}Variable Type with Custom Type Key
By default, the type field is named type, but you can customize it using the typeKey option. Also, the fields option can be omitted if a type has no subfields.
The following example shows a simple page builder configuration with three block types: Heading, Paragraph, and Horizontal Rule.
- name: blocks
label: Blocks
widget: list
typeKey: tag
types:
- name: h2
label: Heading
fields:
- name: text
label: Text
widget: string
- name: p
label: Paragraph
fields:
- name: text
label: Text
widget: string
- name: hr
label: Horizontal Rule[[fields]]
name = "blocks"
label = "Blocks"
widget = "list"
typeKey = "tag"
[[fields.types]]
name = "h2"
label = "Heading"
[[fields.types.fields]]
name = "text"
label = "Text"
widget = "string"
[[fields.types]]
name = "p"
label = "Paragraph"
[[fields.types.fields]]
name = "text"
label = "Text"
widget = "string"
[[fields.types]]
name = "hr"
label = "Horizontal Rule"{
"name": "blocks",
"label": "Blocks",
"widget": "list",
"typeKey": "tag",
"types": [
{
"name": "h2",
"label": "Heading",
"fields": [
{
"name": "text",
"label": "Text",
"widget": "string"
}
]
},
{
"name": "p",
"label": "Paragraph",
"fields": [
{
"name": "text",
"label": "Text",
"widget": "string"
}
]
},
{
"name": "hr",
"label": "Horizontal Rule"
}
]
}{
name: "blocks",
label: "Blocks",
widget: "list",
typeKey: "tag",
types: [
{
name: "h2",
label: "Heading",
fields: [
{
name: "text",
label: "Text",
widget: "string",
},
],
},
{
name: "p",
label: "Paragraph",
fields: [
{
name: "text",
label: "Text",
widget: "string",
},
],
},
{
name: "hr",
label: "Horizontal Rule",
},
],
}Output example:
blocks:
- tag: h2
text: Welcome to Our Site
- tag: p
text: This is the first paragraph of the site.
- tag: hr
- tag: p
text: This is another paragraph after the horizontal rule.[[blocks]]
tag = "h2"
text = "Welcome to Our Site"
[[blocks]]
tag = "p"
text = "This is the first paragraph of the site."
[[blocks]]
tag = "hr"
[[blocks]]
tag = "p"
text = "This is another paragraph after the horizontal rule."{
"blocks": [
{
"tag": "h2",
"text": "Welcome to Our Site"
},
{
"tag": "p",
"text": "This is the first paragraph of the site."
},
{
"tag": "hr"
},
{
"tag": "p",
"text": "This is another paragraph after the horizontal rule."
}
]
}Top-Level List
It’s possible to define a List field at the top level of an output file, using the root option. The configuration below reproduces this Jekyll data file example:
collections:
- name: data
label: Data Files
files:
- name: members
label: Member List
file: _data/members.yml
icon: group
fields:
- name: members
label: Members
label_singular: Member
widget: list
root: true
fields:
- name: name
label: Name
- name: github
label: GitHub account[[collections]]
name = "data"
label = "Data Files"
[[collections.files]]
name = "members"
label = "Member List"
file = "_data/members.yml"
icon = "group"
[[collections.files.fields]]
name = "members"
label = "Members"
label_singular = "Member"
widget = "list"
root = true
[[collections.files.fields.fields]]
name = "name"
label = "Name"
[[collections.files.fields.fields]]
name = "github"
label = "GitHub account"{
"collections": [
{
"name": "data",
"label": "Data Files",
"files": [
{
"name": "members",
"label": "Member List",
"file": "_data/members.yml",
"icon": "group",
"fields": [
{
"name": "members",
"label": "Members",
"label_singular": "Member",
"widget": "list",
"root": true,
"fields": [
{
"name": "name",
"label": "Name"
},
{
"name": "github",
"label": "GitHub account"
}
]
}
]
}
]
}
]
}{
collections: [
{
name: "data",
label: "Data Files",
files: [
{
name: "members",
label: "Member List",
file: "_data/members.yml",
icon: "group",
fields: [
{
name: "members",
label: "Members",
label_singular: "Member",
widget: "list",
root: true,
fields: [
{
name: "name",
label: "Name",
},
{
name: "github",
label: "GitHub account",
},
],
},
],
},
],
},
],
}It also works with a singleton. The configuration below reproduces the same data file example using a singleton:
singletons:
- name: members
label: Member List
file: _data/members.yml
icon: group
fields:
- name: members
label: Members
label_singular: Member
widget: list
root: true
fields:
- name: name
label: Name
- name: github
label: GitHub account[[singletons]]
name = "members"
label = "Member List"
file = "_data/members.yml"
icon = "group"
[[singletons.fields]]
name = "members"
label = "Members"
label_singular = "Member"
widget = "list"
root = true
[[singletons.fields.fields]]
name = "name"
label = "Name"
[[singletons.fields.fields]]
name = "github"
label = "GitHub account"{
"singletons": [
{
"name": "members",
"label": "Member List",
"file": "_data/members.yml",
"icon": "group",
"fields": [
{
"name": "members",
"label": "Members",
"label_singular": "Member",
"widget": "list",
"root": true,
"fields": [
{
"name": "name",
"label": "Name"
},
{
"name": "github",
"label": "GitHub account"
}
]
}
]
}
]
}{
singletons: [
{
name: "members",
label: "Member List",
file: "_data/members.yml",
icon: "group",
fields: [
{
name: "members",
label: "Members",
label_singular: "Member",
widget: "list",
root: true,
fields: [
{
name: "name",
label: "Name",
},
{
name: "github",
label: "GitHub account",
},
],
},
],
},
],
}Output example:
- name: Alice
github: alicehub123
- name: Bob
github: bobgit456
- name: Charlie
github: charliecode789[
{
"name": "Alice",
"github": "alicehub123"
},
{
"name": "Bob",
"github": "bobgit456"
},
{
"name": "Charlie",
"github": "charliecode789"
}
]As you can see, the list is stored directly at the root level of the output file, without a parent key (members). We don’t have a TOML example here because TOML format cannot represent top-level arrays; thus, the root option is ignored for TOML files.