Tina Docs
Introduction
Core Concepts
Querying Content
Editing
Customizing Tina
Going To Production
Media
Drafts
Guides
Further Reference

object Type

The object field is a dynamic field type that creates a nested page in the CMS with the data it contains.

This can be used to create repeated data structures, group related data in the CMS and/or give users the option to choose between a set of templates.

type ObjectField = {
label: string
name: string
type: 'object'
list?: boolean
// `fields` OR `templates` may be provided, not both
fields?: Field[]
templates?: Template[]
/** Customize the default "_template" key that gets set
in a document to identify a block-type.
Only applicable when list: true **/
templatesKey?: string
// See https://tina.io/docs/extending-tina/overview/ for customizing the UI
ui?: {
// Whether or not the Visual Selector is enabled. See https://tina.io/docs/editing/blocks/#adding-a-visual-block-selector-experimental
visualSelector?: boolean,
// defaultItem can only can be used when {list: true}
defaultItem?: Record<string, any> | () => Record<string, any>,
itemProps?(
item: Record<string, any>
): {
label?: string
}
}
}

Usage

Ultimately there are 3 ways to configure this type...

  • With list set to false, the fields array can be used to wrap some data – this appears in the editor as a nested page. This can be used to organise the CMS, such as grouping options together, as in the gif below.
  • With list set to true, the fields array contains the data structure to be repeated – this appears in the editor as above, but grouped as a list.
  • With list set to true, and using templates as opposed to fields the user can select between associated templates – this appears as above, but pressing the + gives you the option to choose between templates.
Scenario: We have a component on our site that needs to hold an array of other field types, so we define it as a type object. Some of the field types within this parent object are also objects themselves.
import type { Template, TinaField } from 'tinacms';
export const featuresTemplate: Template = {
label: 'Feature Block',
name: 'featureBlock',
fields: [
{
name: 'featureItem',
label: 'Feature Items',
type: 'object',
list: true,
ui {
itemProps: (item) => {
return { label: item?.headline };
},
},
fields: [
{ name: 'headline', label: 'Headline', type: 'string' },
{
name: 'description', label: 'Description',
type: 'string', ui: { component: 'textarea' }
},
{
name: 'buttons',
label: 'Buttons',
list: true,
type: 'object',
ui: {
visualSelector: true,
itemProps: (item) => {
return { label: item?.label };
},
},
templates: [
actionsButtonTemplate as Template,
codeButtonTemplate as Template,
modalButtonTemplate as Template
],
},
] as TinaField[],
},
],
};

Code-Block Breakdown

  • We originally have a list of feature item objects, each of these objects store an array [Headline, description, buttons]
  • Each feature item in the list has a dynamic label so that we can differentiate between each feature item in our editor (lines 12-14)
  • We then have some reusable objects which are stored as a list within our buttons element of the featureBlock array
  • Because each of our unique 3 button templates also stores an array of variables themself, we use the type: object

An example of what this object array would look like is

{
'headline': 'Feature Item 1',
'description': 'All stuff Tina!',
'buttons': [
{
label: 'Button A',
href: '/docs',
},
{
label: 'Button B',
href: '/blog'
}
],
},
{
'headline': 'Feature Item 2',
'description': 'This feature has no buttons'
}

More Examples

Tina will generate the appropriate component depending on the configuration provided.

A basic object configuration

{
label: "Testimonial",
name: "testimonial",
type: "object",
fields: [
{
label: "Author",
name: "author",
type: "string"
},
{
label: "Role",
name: "role",
type: "string"
},
{
label: "Quote",
name: "quote",
type: "string",
ui: {
component: "textarea"
}
}
]
}

As a list with default values

{
label: "Testimonials",
name: "testimonials",
type: "object",
list: true,
ui: {
itemProps: (item) => {
return { label: `${item?.author} ( ${item?.role} ) ` }
},
defaultItem: {
author: "Judith Black",
role: "CEO",
quote: "Lorem ipsum dol..."
}
},
fields: [
{
name: "author",
// ...
},
{
name: "role",
// ...
},
{
name: "quote",
// ...
}
]
}

Using list object as a wrapper for other types

Number, boolean, datetime, reference and rich-text field types can be used as the sole field of an object to create a list of one of those types.

{
label: "Author List",
name: "authorList",
type: "object",
list: true,
fields: [
{
label: 'Author',
name: 'author',
type: 'reference',
collections: ['author'],
},
]
}

Using templates instead of fields

{
label: "Page Blocks",
name: "pageBlocks",
type: "object",
list: true,
templates: [
{
label: "CTA",
name: "cta",
fields: [...]
},
{
label: "Testimonial",
name: "testimonial",
fields: [...]
}
]
}

Last Edited: November 26, 2024