Rich Text Field

The Admin component is built on the powerful slatejs editor and is meant to be as extensible and customizable as possible.

Config

OptionDescription
name *To be used as the property name when stored and retrieved from the database.
labelUsed as a field label in the Admin panel and to name the generated GraphQL type.
validateProvide a custom validation function that will be executed on both the Admin panel and the backend. More
saveToJWTIf this field is top-level and nested in a config supporting Authentication, include its data in the user JWT.
hooksProvide field-based hooks to control logic for this field. More
accessProvide field-based access control to denote what users can see and do with this field's data. More
hiddenRestrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel.
defaultValueProvide data to be used for this field's default value.
localizedEnable localization for this field. Requires localization to be enabled in the Base config.
requiredRequire this field to have a value.
adminAdmin-specific configuration. See below for more detail.

* An asterisk denotes that a property is required.

Admin config

In addition to the default field admin config, the Rich Text editor allows for the following admin properties:

placeholder

Set this property to define a placeholder string in the text input.

elements

The elements property is used to specify which built-in or custom SlateJS elements should be made available to the field within the admin panel.

The default elements available in Payload are:

leaves

The leaves property specifies built-in or custom SlateJS leaves to be enabled within the Admin panel.

The default leaves available in Payload are:

  • bold
  • code
  • italic
  • strikethrough
  • underline

Relationship element

The built-in relationship element is a powerful way to reference other Documents directly within your Rich Text editor.

Relationships are populated dynamically into your Rich Text field' content. Within the REST and Local APIs, any present RichText relationship elements will respect the depth option that you pass, and will be populated accordingly. In GraphQL, each richText field accepts an argument of depth for you to utilize.

Specifying which elements and leaves to allow

To specify which default elements or leaves should be allowed to be used for this field, define arrays that contain string names for each element or leaf you wish to enable. To specify a custom element or leaf, pass an object with all corresponding properties as outlined below. View the example to reference how this all works.

Building custom elements and leaves

You can design and build your own Slate elements and leaves to extend the editor with your own functionality. To do so, first start by reading the SlateJS documentation and looking at the Slate examples to familiarize yourself with the SlateJS editor as a whole.

Once you're up to speed with the general concepts involved, you can pass in your own elements and leaves to your field's admin config.

Both custom elements and leaves are defined via the following config:

PropertyDescription
name *The name to be used as a type for this element.
Button *A React component to be rendered in the Rich Text toolbar.
pluginsAn array of plugins to provide to the Rich Text editor.

Custom Elements also require the Element property set to a React component to be rendered as the Element within the rich text editor itself.

Custom Leaf objects follow a similar pattern but require you to define the Leaf property instead.

Example

collections/ExampleCollection.js

{
slug: 'example-collection',
fields: [
{
name: 'content', // required
type: 'richText', // required
defaultValue: [{
children: [{ text: 'Here is some default content for this field' }],
}]
required: true,
admin: {
elements: [
'h2',
'h3',
'h4',
'link',
{
name: 'cta',
Button: CustomCallToActionButton,
Element: CustomCallToActionElement,
plugins: [
// any plugins that are required by this element go here
]
}
],
elements: [
'bold',
'italic',
{
name: 'highlight',
Button: CustomHighlightButton,
Leaf: CustomHighlightLeaf,
plugins: [
// any plugins that are required by this leaf go here
]
}
]
}
}
]
}

For more examples regarding how to define your own elements and leaves, check out the example RichText collection within the Payload source code.

Generating HTML

As the Rich Text field saves its content in a JSON format, you'll need to render it as HTML yourself. Here is an example for how to generate JSX / HTML from Rich Text content:

import React, { Fragment } from 'react';
import escapeHTML from 'escape-html';
import { Text } from 'slate';
const serialize = (children) => children.map((node, i) => {
if (Text.isText(node)) {
let text = <span dangerouslySetInnerHTML={{ __html: escapeHTML(node.text) }} />;
if (node.bold) {
text = (
<strong key={i}>
{text}
</strong>
);
}
if (node.code) {
text = (
<code key={i}>
{text}
</code>
);
}
if (node.italic) {
text = (
<em key={i}>
{text}
</em>
);
}
// Handle other leaf types here...
return (
<Fragment key={i}>
{text}
</Fragment>
);
}
if (!node) {
return null;
}
switch (node.type) {
case 'h1':
return (
<h1 key={i}>
{serialize(node.children)}
</h1>
);
// Iterate through all headings here...
case 'h6':
return (
<h6 key={i}>
{serialize(node.children)}
</h6>
);
case 'quote':
return (
<blockquote key={i}>
{serialize(node.children)}
</blockquote>
);
case 'ul':
return (
<ul key={i}>
{serialize(node.children)}
</ul>
);
case 'ol':
return (
<ol key={i}>
{serialize(node.children)}
</ol>
);
case 'li':
return (
<li key={i}>
{serialize(node.children)}
</li>
);
case 'link':
return (
<a
href={escapeHTML(node.url)}
key={i}
>
{serialize(node.children)}
</a>
);
default:
return (
<p key={i}>
{serialize(node.children)}
</p>
);
}
});
Next

Row Field