Rich text editor in the frontend form
New in version 11.2.0
Textarea elements of the event form based on EXT:form can be edited with a CKEditor 5.
Textarea elements of the event form based on EXT:form (site setting
events2.) can be edited with a small CKEditor 5. Frontend
users can format the text, and formatting added by editors in the backend
is kept when the event is edited in the frontend. By default, the element
detail- (column detail_) gets the editor.
Further elements can be added by configuration.
The feature is disabled by default. Without it, all elements are plain textareas as before.
Table of contents
Requirements for the frontend rich text editor
- The event form based on EXT:form (site setting
events2.).form. use Ext Form - The system extension EXT:rte_ckeditor ( typo3/cms-rte-ckeditor ). The editor is not activated if it is not installed.
No build step (npm, webpack) is needed. The CKEditor 5 ES modules, translations and styles shipped with EXT:rte_ckeditor are used.
Site settings of the frontend rich text editor
The following settings are provided by the site set jweiland/
and are available in TypoScript as
plugin., see
richText.enable.
| Name | Type | Default |
|---|---|---|
| bool |
false
|
|
| string |
detail-
|
-
- Type
- bool
- Default
false
Use CKEditor 5 of EXT:rte_ckeditor for the rich text elements of the event form based on EXT:form.
-
- Type
- string
- Default
detail-description
Comma-separated identifiers of the form elements which get the rich text editor. Elements with
datain theirType: rich Text dbget the editor, too.Mapping
Enable the frontend rich text editor
Enable the site setting
events2.form.richText.enable
of the site set jweiland/.
That is all for the description: the element detail- is the
default of the site setting
events2.form.richText.elements.
This works for overridden copies of New as well, as
long as they use this identifier.
Example: Enable the rich text editor for the description
events2:
form:
richText:
enable: true
Rich text elements of the event form
An element of the form is a rich text element if
- its identifier is listed in the site setting events2.form.richText.elements or
- it has
datain itsType: rich Text db.Mapping
If the editor is enabled, events2 configures each rich text element automatically:
- The
dataof the element isType rich, so the edit form gets the stored HTML instead of plain text.Text - The mapping of the element in the
SavegetsEvent Finisher sanitize(instead ofRich Text: true convertorPlain Text To Html normalize).Plain Text - While rendering, the textarea gets the attribute
data-with the options of the editor, including the allowed tags of its column (see Toolbar of the frontend rich text editor). The assets are only loaded on pages of the form which contain a rich text element. Each textarea gets its own editor.events2- rich- text
If the editor is disabled, rich text elements fall back to plain text:
data and convert instead of
sanitize.
Important
The database column of a rich text element should be a rich text field
in TCA ('enable), like detail_.
Otherwise, the backend shows the HTML source of the value. The column
teaser, for example, is a plain text field with a maximum of 255
characters and is not a suitable target, unless you change its TCA.
The editor of an element is configured for the column
properties. of the table
properties.. The table is optional and defaults to
tx_. Set it only for elements which are stored
in another table, so the toolbar matches the allowed tags of that column.
Use the same table as the mapping of the element in the
Save:
- label: 'Notes of the organizer'
type: Textarea
identifier: organizer-notes
properties:
dbMapping:
table: tx_events2_domain_model_organizer
column: tx_myext_notes
dataType: richText
Example: Add a rich text editor to an additional form element
Add an own textarea to your copy of New and map it
to an own column of the event table, which you have configured with
'enable in TCA:
- label: 'Program'
type: Textarea
identifier: program
properties:
dbMapping:
column: tx_myext_program
# Optional: Instead of listing "program" in the site setting
dataType: richText
Map the element in the Save options of the table
tx_:
finishers:
1:
identifier: SaveEventFinisher
options:
4:
table: tx_events2_domain_model_event
elements:
program:
mapOnDatabaseColumn: tx_myext_program
Then either keep data in the form definition or add
the identifier to the site setting:
events2:
form:
richText:
enable: true
elements: 'detail-description, program'
Loaded files of the frontend rich text editor
The import map of the CKEditor modules is defined in
EXT: and rendered by the
Page of TYPO3 (<script type="importmap">,
respecting the Content Security Policy of the site). The ES module
EXT: creates
an editor for each textarea with the attribute
data-. It loads the UI translation of the current
site language. The style sheets
EXT: and
EXT: are added with
the Asset.
The files are about 1.6 MB uncompressed and about 400 KB compressed with gzip.
Toolbar of the frontend rich text editor
The toolbar is built from the tags which are allowed for the column of the element (see Allowed markup of the frontend rich text editor). With the default configuration, it contains:
- Heading: Paragraph, Heading 2, Heading 3 (Heading 1 is used for the title of the event)
- Bold, Italic
- Bulleted list, numbered list
- Link with the protocols
http,https,mailtoandteland the option Open in a new tab - Undo, Redo
New in version 11.2.0
The headings and toolbar items follow the allowed tags of the ModifyRichTextSanitizerConfigurationEvent.
The editor gets one heading option for each allowed element of
<h1> to <h6>. The titles of the headings are translated
by CKEditor. The heading dropdown is only shown if at least one heading is
allowed. The toolbar items are only shown if their element is allowed:
- Bold:
<strong> - Italic:
<em> - Bulleted list:
<ul> - Numbered list:
<ol> - Link:
<a>
Undo and Redo are always available. Allowed
elements without a toolbar item, like <u> or
<blockquote>, are kept when the value is saved, but can not be
selected in the editor.
Toolbar items which do not fit into the width of the form are grouped into a dropdown. The toolbar can be focused with Alt + F10.
Allowed markup of the frontend rich text editor
The submitted HTML is sanitized on the server with typo3/html-sanitizer , as a request can bypass the editor. By default, only these tags are allowed:
<p>,<br>,<strong>,<em>,<h2>,<h3>,<ul>,<ol>,<li><a>withhref(http,https,mailto,tel) andtarget="_, which getsblank" rel="noopener noreferrer"
<b> is converted to <strong>, <i> to <em>
and <h1>, <h4>, <h5>, <h6> to
<p>. All attributes like class, style or
on* are removed. Links with other protocols like javascript: or
data: are removed, their text is kept. <script>,
<style>, <iframe>, images, forms and similar elements are
removed including their content. The text of all other elements is kept.
Other block elements like <div>, <blockquote> or table
cells become paragraphs. Text and inline formatting outside of blocks is
wrapped into a paragraph like the editor does, so <strong>,
<em> and links are kept.
The tags can be modified with the PSR-14 event
Modify, see
Modify the allowed markup of the frontend rich text editor.
Links to records (t3://) in the frontend rich text editor
Links like t3:// or t3:// can only be added in
the backend. They are kept if exactly the same link is already part of the
value stored in the column of the record which is updated. New or modified
t3:// links are removed, their text is kept. For records of the event
table, the event of the edit form is used. For other tables, the uid of
the where of the finisher (mode update) is used.
Afterwards, the value is transformed with the RTE configuration of the
backend (Rte), so it is stored the same way as if it was
saved in the backend.
Modify the allowed markup of the frontend rich text editor
New in version 11.2.0
The PSR-14 event Modify
allows to modify the tags of the rich text sanitizer and of the
toolbar of the frontend editor.
The PSR-14 event
JWeiland
is dispatched for each rich text element:
- While rendering the form element, to build the headings and toolbar
items of the editor (see Toolbar of the frontend rich text editor).
Table and column are taken from
properties.(default:db Mapping. table tx_) andevents2_ domain_ model_ event properties.of the form element.db Mapping. column - Each time a submitted value which contains HTML is sanitized. Values without any tag are converted like plain text and do not dispatch the event.
The event receives the defaults, which are defined as constants in
JWeiland. So one
listener configures both the editor and the sanitizing on the server.
Note
Only elements with a toolbar item can be selected in the editor:
headings <h1> to <h6>, <strong>, <em>,
<ul>, <ol> and <a>. Other allowed elements, like
<u> or <blockquote>, are kept if they are already part
of the value, for example because they were added by an editor in the
backend, or if they are submitted with a request.
Methods of the ModifyRichTextSanitizerConfigurationEvent
get/Allowed Tags () setAllowed Tags (array $allowed Tags) - Elements which are kept. Default:
<p>,<br>,<strong>,<em>,<h2>,<h3>,<ul>,<ol>,<li>and<a>. get/Mapped Tags () setMapped Tags (array $mapped Tags) - Elements which are renamed, as array of source tag name to target tag
name, for example
'b' => 'strong'. Default:<b>to<strong>,<i>to<em>and<h1>,<h4>,<h5>,<h6>to<p>. get/Removed Tags () setRemoved Tags (array $removed Tags) - Elements which are removed including their content, for example
<script>,<img>,<form>or<video>. get/Block Tags () setBlock Tags (array $block Tags) - Elements which start a new block, for example
<div>,<blockquote>or<td>. A block element which is not allowed becomes a paragraph if it does not contain other block elements. Otherwise, it is unwrapped and only its content is kept. getTable () - Table of the column the HTML is stored in, for example
tx_. Empty if unknown.events2_ domain_ model_ event getColumn () - Column the HTML is stored in, for example
detail_. Empty if unknown.information
Rules for the configuration of the rich text sanitizer
After all listeners are called, the configuration is normalized:
- Tag names are converted to lower case. Invalid tag names are ignored.
<p>is always allowed, as inline content outside of blocks is wrapped into paragraphs.- Elements with active or embedded content can never be allowed:
<applet>,<base>,<embed>,<frame>,<frameset>,<iframe>,<link>,<math>,<meta>,<noscript>,<object>,<script>,<style>,<svg>and<template>. They are always removed including their content. - Removed tags take precedence over allowed tags.
- A mapping is only used if its target is allowed and its source is
neither allowed nor removed. So allowing
<h4>is enough to keep it, the default mapping of<h4>to<p>is skipped. - Allowed elements never get any attribute. The only exception is
<a>, which keeps a checkedhrefandtarget="_.blank"
After sanitizing, the value is transformed with the RTE configuration of
the backend (Rte). An element allowed by the event must
be allowed by the RTE configuration of the column as well. The default RTE
configuration keeps <h4>, for example.
Example: Allow h4 in the description of events
The following event listener allows <h4> for the column
detail_ of the event table only. The editor of the
description gets the additional heading Heading 4, and the
heading is kept when the event is saved. All other rich text elements
keep the default configuration.
<?php
declare(strict_types=1);
namespace MyVendor\MySitepackage\EventListener;
use JWeiland\Events2\Event\ModifyRichTextSanitizerConfigurationEvent;
use TYPO3\CMS\Core\Attribute\AsEventListener;
#[AsEventListener(identifier: 'my-sitepackage/allow-heading-4')]
final class AllowHeading4EventListener
{
public function __invoke(ModifyRichTextSanitizerConfigurationEvent $event): void
{
if ($event->getTable() !== 'tx_events2_domain_model_event'
|| $event->getColumn() !== 'detail_information'
) {
return;
}
// Keep <h4> instead of converting it to <p>
$event->setAllowedTags([...$event->getAllowedTags(), 'h4']);
}
}
The attribute # registers the listener, see
Event dispatcher (PSR-14 events).
Frontend form without JavaScript
Without JavaScript, the plain textarea is shown. For new events, plain text can be entered as before. When editing an event, the textarea contains the stored HTML. Values without any tag are converted like the plain text description.