Configure custom backend preview for content element
To allow editors a smoother experience, all custom content elements and plugins should be configured with a corresponding backend preview that shows an approximation of the element's appearance in the TYPO3 page module. The following sections describe how to achieve that.
A preview renderer is used to facilitate (record) previews in TYPO3. This class is responsible for generating the preview and the wrapping.
The default preview renderer is
\TYPO3\
and handles the Core's built-in content types (field
CType
in table
tt_).
Extend the default preview renderer
There are two ways to provide previews for your custom content types: via page TSconfig or event listener.
Preview rendering with a Fluid template and page TSconfig
Changed in version 14.0 Breaking: #92434 - Use Record API in Page Module Preview Rendering
A
\TYPO3\ is passed as variable
{record} to the Fluid Template. The fields are not passed as direct
variables anymore. {pi_ has been replaced by
{record..
This is the "integrator" way, no PHP coding is required. It needs only some page TSconfig and a Fluid template.
mod.web_layout {
tt_content {
preview {
# Your CType
example_ctype = EXT:my_extension/Resources/Private/Templates/Preview/MyCType.fluid.html
}
}
}
For more details see the TSconfig Reference.
In the Fluid template, the following variables are available:
- The current record as object (
Record) in variable{record}
<h2>{record.header}</h2>
<p>{record.bodytext}</p>
<f:if condition="{record.image}">
<p>Image UID: {record.image.uid}</p>
</f:if>
<f:variable name="path" value="s_messages/settings" />
<small>{record.pi_flexform.{path}.welcome_header}</small>
Or, the following (same result):
<small>{record.pi_flexform.sheets.s_messages.settings.welcome_header}</small>
-<h2>{header}</h2>
+<h2>{record.header}</h2>
-<p>{bodytext}</p>
+<p>{record.bodytext}</p>
-<small>{pi_flexform_transformed.settings.welcome_header}</small>
+<small>{record.pi_flexform.sheets.s_messages.settings.welcome_header}</small>
Event listener
This requires at least some PHP coding, but allows more flexibility in accessing and processing the content elements properties.
The event
Page is being dispatched by the
Standard. You can listen to it with your own
event listener.
Have a look at this showcase implementation.
For general information see the chapter on implementing an event listener.
Writing a preview renderer
Changed in version 14.0
The @internal class
Grid has been
updated to work with Record objects.
A custom preview renderer must implement the interface
\TYPO3\ which contains
the following API methods:
-
interface
PreviewRendererInterface -
- Fully qualified name
-
\TYPO3\CMS\ Backend\ Preview\ Preview Renderer Interface
Interface PreviewRendererInterface
Contract for classes capable of rendering previews of a given record from a table. Responsible for rendering preview header, preview content and wrapping of those two values.
Responsibilities are segmented into three methods, one for each responsibility, which is done in order to allow overriding classes to change those parts individually without having to replace other parts. Rather than relying on implementations to be friendly and divide code into smaller pieces and give them (at least) protected visibility, the key methods are instead required on the interface directly.
Callers are then responsible for calling each method and combining/wrapping the output appropriately.
renderPageModulePreviewHeader(\TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem $item)-
Dedicated method for rendering preview header HTML for the page module only. Receives the GridColumnItem that contains the record for which a preview header should be rendered and returned.
- param $item
-
the item
- Returns
-
string
renderPageModulePreviewContent(\TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem $item)-
Dedicated method for rendering preview body HTML for the page module only. Receives the GridColumnItem that contains the record for which a preview should be rendered and returned.
- param $item
-
the item
- Returns
-
string
-
Render a footer for the record to display in page module below the body of the item's preview.
- param $item
-
the item
- Returns
-
string
wrapPageModulePreview(string $previewHeader, string $previewContent, \TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem $item)-
Dedicated method for wrapping a preview header and body HTML. Receives $item, an instance of GridColumnItem holding among other things the record, which can be used to determine appropriate wrapping.
- param $previewHeader
-
the previewHeader
- param $previewContent
-
the previewContent
- param $item
-
the item
- Returns
-
string
Implementing these methods allows you to control the exact composition of the preview.
This means assuming your preview renderer returns
<h4>Header</
from the header render method and
<p>Body</ from the preview content
rendering method and your wrapping method does
return '<div>' . $preview then the
entire output becomes
<div><h4>Header</ when
combined.
Changed in version 15.0
Standard has been turned
into a stateless, dependency-injected service. It is now declared
final
and can no longer be subclassed.
The standard renderer may be composed and its rendering methods delegated to where its output
is desired, as
Form demonstrates.
Render single fields with the record field preview processor
New in version 14.2 Feature: #108819 - RecordFieldPreviewProcessor for custom PreviewRenderers
These methods used to sit in
Standard,
so reaching them meant extending that class.
A preview renderer injects the service
Record to render
a single field of a record:
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\Preview;
use TYPO3\CMS\Backend\Preview\PreviewRendererInterface;
use TYPO3\CMS\Backend\Preview\RecordFieldPreviewProcessor;
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem;
final readonly class ConferenceRenderer implements PreviewRendererInterface
{
public function __construct(
private RecordFieldPreviewProcessor $fieldProcessor,
) {}
public function renderPageModulePreviewHeader(
GridColumnItem $item,
): string {
$record = $item->getRecord();
$request = $item->getContext()->getCurrentRequest();
$header = $this->fieldProcessor->prepareField($record, 'header');
if ($header === null) {
return '';
}
// The header links to the edit form of the record
return $this->fieldProcessor->linkToEditForm(
'<strong>' . $header . '</strong>',
$record,
$request,
);
}
public function renderPageModulePreviewContent(
GridColumnItem $item,
): string {
$record = $item->getRecord();
$parts = [
$this->fieldProcessor->prepareFieldWithLabel($record, 'location'),
$this->fieldProcessor->prepareText($record, 'bodytext', 500),
$this->fieldProcessor->prepareFiles($record->get('media')),
];
return implode('<br />', array_filter($parts));
}
public function renderPageModulePreviewFooter(
GridColumnItem $item,
): string {
return '';
}
public function wrapPageModulePreview(
string $previewHeader,
string $previewContent,
GridColumnItem $item,
): string {
return $previewHeader . $previewContent;
}
}
Every method returns HTML that is ready to be output, or null when the
record has no such field or the field is empty. There is one for a field with
and one without its label from TCA, one for a shortened text, one for escaped
and one for sanitized HTML, one for thumbnails of file references, and one
that wraps a text in a link to the edit form of the record.
Configuring the implementation
Individual preview renderers can be defined by using one of the following approaches:
-
Any record
$GLOBALS['TCA'][$table]['ctrl']['previewRenderer'] = MyVendor\MyExtension\Preview\MyPreviewRenderer::class;Copied!This specifies the preview renderer to be used for any record in
$table. -
Table has a type field/attribute
$GLOBALS['TCA'][$table]['types'][$type]['previewRenderer'] = MyVendor\MyExtension\Preview\MyPreviewRenderer::class;Copied!This specifies the preview renderer only for records of type
$typeas determined by the type field of your table.
Like all other content types, text, textpic, textmedia and
image use the standard
Standard. To customize
previews for these elements, use the
page TSconfig or
event listener approach described
above (instead of registering type-specific preview renderers as in the past).
Note
The recommended location is in the
ctrl
array in your extension's Configuration/
or Configuration/ file. The former is used
when your extension is the one that creates the table, the latter is used
when you need to override TCA properties of tables added by the Core or
other extensions.