There was a `<br/>` tag, which was visible on the docs page. Also, I removed spacing from the second tip box, to keep in consistent with tips in other places in docs.
219 lines
14 KiB
Plaintext
219 lines
14 KiB
Plaintext
---
|
|
title: Blocks Field
|
|
label: Blocks
|
|
order: 30
|
|
desc: The Blocks Field is a great layout build and can be used to construct any flexible content model. Learn how to use Block Fields, see examples and options.
|
|
keywords: blocks, fields, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
|
---
|
|
|
|
The Blocks Field is **incredibly powerful** storing an array of objects based on the fields that your define, where each item in the array is a "block" with its own unique schema.
|
|
|
|
Blocks are a great way to create a flexible content model that can be used to build a wide variety of content types, including:
|
|
|
|
- A layout builder tool that grants editors to design highly customizable page or post layouts. Blocks could include configs such as `Quote`, `CallToAction`, `Slider`, `Content`, `Gallery`, or others.
|
|
- A form builder tool where available block configs might be `Text`, `Select`, or `Checkbox`.
|
|
- Virtual event agenda "timeslots" where a timeslot could either be a `Break`, a `Presentation`, or a `BreakoutSession`.
|
|
|
|
<LightDarkImage
|
|
srcLight="https://payloadcms.com/images/docs/fields/blocks.png"
|
|
srcDark="https://payloadcms.com/images/docs/fields/blocks-dark.png"
|
|
alt="Admin Panel screenshot of add Blocks drawer view"
|
|
caption="Admin Panel screenshot of add Blocks drawer view"
|
|
/>
|
|
|
|
To add a Blocks Field, set the `type` to `blocks` in your [Field Config](./overview):
|
|
|
|
```ts
|
|
import type { Field } from 'payload'
|
|
|
|
export const MyBlocksField: Field = {
|
|
// ...
|
|
// highlight-start
|
|
type: 'blocks',
|
|
blocks: [
|
|
// ...
|
|
],
|
|
// highlight-end
|
|
}
|
|
```
|
|
|
|
## Config Options
|
|
|
|
| Option | Description |
|
|
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
|
| **`label`** | Text used as the heading in the Admin Panel or an object with keys for each language. Auto-generated from name if not defined. |
|
|
| **`blocks`** * | Array of [block configs](/docs/fields/blocks#block-configs) to be made available to this field. |
|
|
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
|
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. |
|
|
| **`maxRows`** | A number for the most allowed items during validation when a value is present. |
|
|
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
|
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
|
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
|
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API response or the Admin Panel. |
|
|
| **`defaultValue`** | Provide an array of block data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
|
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this field will be kept, so there is no need to specify each nested field as `localized`. |
|
|
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
|
| **`labels`** | Customize the block row labels appearing in the Admin dashboard. |
|
|
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
|
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
|
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
|
|
|
_* An asterisk denotes that a property is required._
|
|
|
|
## Admin Options
|
|
|
|
The customize the appearance and behavior of the Blocks Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
|
|
|
|
```ts
|
|
import type { Field } from 'payload'
|
|
|
|
export const MyBlocksField: Field = {
|
|
// ...
|
|
admin: { // highlight-line
|
|
// ...
|
|
},
|
|
}
|
|
```
|
|
|
|
The Blocks Field inherits all of the default options from the base [Field Admin Config](../admin/fields#admin-options), plus the following additional options:
|
|
|
|
| Option | Description |
|
|
| ------------------- | ---------------------------------- |
|
|
| **`initCollapsed`** | Set the initial collapsed state |
|
|
| **`isSortable`** | Disable order sorting by setting this value to `false` |
|
|
|
|
#### Customizing the way your block is rendered in Lexical
|
|
|
|
If you're using this block within the [Lexical editor](/docs/rich-text/overview), you can also customize how the block is rendered in the Lexical editor itself by specifying custom components.
|
|
|
|
- `admin.components.Label` - pass a custom React component here to customize the way that the label is rendered for this block
|
|
- `admin.components.Block` - pass a component here to completely override the way the block is rendered in Lexical with your own component
|
|
|
|
This is super handy if you'd like to present your editors with a very deliberate and nicely designed block "preview" right in your rich text.
|
|
|
|
For example, if you have a `gallery` block, you might want to actually render the gallery of images directly in your Lexical block. With the `admin.components.Block` property, you can do exactly that!
|
|
|
|
<Banner type="success">
|
|
**Tip:**
|
|
If you customize the way your block is rendered in Lexical, you can import utility components to easily edit / remove your block - so that you don't have to build all of this yourself.
|
|
</Banner>
|
|
|
|
To import these utility components for one of your custom blocks, you can import the following:
|
|
|
|
```ts
|
|
import {
|
|
// Edit block buttons (choose the one that corresponds to your usage)
|
|
// When clicked, this will open a drawer with your block's fields
|
|
// so your editors can edit them
|
|
InlineBlockEditButton,
|
|
BlockEditButton,
|
|
|
|
// Buttons that will remove this block from Lexical
|
|
// (choose the one that corresponds to your usage)
|
|
InlineBlockRemoveButton,
|
|
BlockRemoveButton,
|
|
|
|
// The label that should be rendered for an inline block
|
|
InlineBlockLabel,
|
|
|
|
// The default "container" that is rendered for an inline block
|
|
// if you want to re-use it
|
|
InlineBlockContainer,
|
|
|
|
// The default "collapsible" UI that is rendered for a regular block
|
|
// if you want to re-use it
|
|
BlockCollapsible,
|
|
|
|
} from '@payloadcms/richtext-lexical/client'
|
|
```
|
|
|
|
## Block Configs
|
|
|
|
Blocks are defined as separate configs of their own.
|
|
|
|
<Banner type="success">
|
|
**Tip:**
|
|
Best practice is to define each block config in its own file, and then import them into your
|
|
Blocks field as necessary. This way each block config can be easily shared between fields. For
|
|
instance, using the "layout builder" example, you might want to feature a few of the same blocks
|
|
in a Post collection as well as a Page collection. Abstracting into their own files trivializes
|
|
their reusability.
|
|
</Banner>
|
|
|
|
| Option | Description |
|
|
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| **`slug`** * | Identifier for this block type. Will be saved on each block as the `blockType` property. |
|
|
| **`fields`** * | Array of fields to be stored in this block. |
|
|
| **`labels`** | Customize the block labels that appear in the Admin dashboard. Auto-generated from slug if not defined. |
|
|
| **`imageURL`** | Provide a custom image thumbnail to help editors identify this block in the Admin UI. |
|
|
| **`imageAltText`** | Customize this block's image thumbnail alt text. |
|
|
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
|
| **`graphQL.singularName`** | Text to use for the GraphQL schema name. Auto-generated from slug if not defined. NOTE: this is set for deprecation, prefer `interfaceName`. |
|
|
| **`dbName`** | Custom table name for this block type when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from slug if not defined. |
|
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
|
|
|
### Auto-generated data per block
|
|
|
|
In addition to the field data that you define on each block, Payload will store two additional properties on each block:
|
|
|
|
**`blockType`**
|
|
|
|
The `blockType` is saved as the slug of the block that has been selected.
|
|
|
|
**`blockName`**
|
|
|
|
The Admin Panel provides each block with a `blockName` field which optionally allows editors to label their blocks for better editability and readability.
|
|
|
|
## Example
|
|
|
|
`collections/ExampleCollection.js`
|
|
|
|
```ts
|
|
import { Block, CollectionConfig } from 'payload'
|
|
|
|
const QuoteBlock: Block = {
|
|
slug: 'Quote', // required
|
|
imageURL: 'https://google.com/path/to/image.jpg',
|
|
imageAltText: 'A nice thumbnail image to show what this block looks like',
|
|
interfaceName: 'QuoteBlock', // optional
|
|
fields: [
|
|
// required
|
|
{
|
|
name: 'quoteHeader',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'quoteText',
|
|
type: 'text',
|
|
},
|
|
],
|
|
}
|
|
|
|
export const ExampleCollection: CollectionConfig = {
|
|
slug: 'example-collection',
|
|
fields: [
|
|
{
|
|
name: 'layout', // required
|
|
type: 'blocks', // required
|
|
minRows: 1,
|
|
maxRows: 20,
|
|
blocks: [
|
|
// required
|
|
QuoteBlock,
|
|
],
|
|
},
|
|
],
|
|
}
|
|
```
|
|
|
|
## TypeScript
|
|
|
|
As you build your own Block configs, you might want to store them in separate files but retain typing accordingly. To do so, you can import and use Payload's `Block` type:
|
|
|
|
```ts
|
|
import type { Block } from 'payload'
|
|
```
|