Daniel Siepmann - Coding is Art

Blog Post

TYPO3 RTE for Input Fields

Published: , Updated:

Tested with TYPO3: 10 LTS

Topics: typo3


Sometimes a headline needs to use line breaks or formatting like italic words. Some integrators define placeholders like [BR] which get substituted. We use TYPO3 native RTE functionality with stripped down configuration. This small post describes how we set it up. The goal is to have a small field and features like limited number of characters and reduced formatting possibilities.

A TYPO3 input field with a lable and RTE. The RTE is one line height and has a wordcount limiting the number of characters to input. The toolbar of RTE is reduced to supscript, subscript and inserting special characters. The current input shows a normal text, supscript and special characters. There is no wrapping in paragraph.
Figure i52: Screenshot of the final result for an example field with reduced RTE configuration. Mimicking a TYPO3 input field with a reduced RTE feature set.

The Problem

Sometimes editors need to insert line breaks <br> or special characters like ⓒ and a reduced set of formatting like superscript or italic within headlines or other input fields of TYPO3. This might be necessary because a headline references a product or company.

But that's not possible with TYPO3 native input fields. Editors might not be aware of system features to insert special characters and even then they won't be able to insert line breaks or formatting within those fields.

Existing Approaches

Some approach we've seen so far:

Provide a documentation with special characters for copy and paste.
We don't like this approach as editors need to switch between TYPO3 and another system holding the documentation for copy and paste which itself is not a nice workflow.

Provide special sequences like [BR] (good old BB-Code style 😉). Those become replaced via TypoScript.
We don't like this as well as you need to document those sequences. And they are more or less HTML in the end, just different braces. One big goal of most CMS is to remove the need for editors to write HTML.

Our Approach

We thought we could use a very reduced RTE configuration for those fields. The goal would be to have a small input field instead of a huge text area. Furthermore, only the necessary formatting should be provided, resulting in a very small toolbar. That would allow an already known way to format text and insert special characters. Editors won't need to learn something new.

TYPO3 offers the option rows for <textarea> inputs to define how large an input should be. Furthermore, TYPO3 provides a max option for input to limit the number of characters. That's important to not lose input after persisting to database. Both should be respected as well. Allowing integrators and developers to use existing approaches and documented options.

TYPO3 by default processes the input when storing and retrieving from database. It for example will wrap lines with <p> tags. We don't want that, as it should be handled like a normal input field.

We use a dedicated RTE configuration and a small EventListener. The configuration will provide the wordcount plugin, adjust the processing of the input and define which formatting options should be available. The Listener should connect the TCA configuration for rows and max to the RTE, by adjusting the configuration.

The Configuration

The configuration of figure i52 looks like this:

  - {resource: "EXT:rte_ckeditor/Configuration/RTE/Editor/Base.yaml"}
  - {resource: "EXT:e2_core/Configuration/RTE/Editor/SpecialChars.yaml"}

    allowedContent: true
    enableContextMenu: false
    forcePasteAsPlainText: true
    clipboard_defaultContentType: 'text'

      - ['Subscript', 'Superscript', '-', 'SpecialChar']

      showRemaining: true
      showParagraphs: false
      showWordCount: false
      showCharCount: true
      # Filled by Event based on TCA configuration
      # maxCharCount: 255

    autoParagraph: false
    enterMode: 2 # <br> instead of <p>

      - wordcount
      - specialchar

      - resize
      - autogrow

  overruleMode: nothing
    - sub
    - sup
    - br

This removes some unwanted features like autogrow, manual resize and context menu.

It also only allows the expected formatting and tags. Furthermore, it configures that line breaks instead of paragraphs should be inserted.

It also imports a global configuration defining the actual special characters needed by editors in this system. TYPO3 v12 will update to CKEditor 5 where special characters UI becomes event better, see: https://ckeditor.com/docs/ckeditor5/latest/features/special-characters.html.

Wordcount is also pre-configured. It will behave like max of input fields and prevent further characters exceeding the maximum count. The count itself is not defined but will be inserted via EventListener based on TCA configuration. One could pre-configure a value within the configuration which can be overwritten via TCA.

The overruleMode: nothing blocks TYPO3 default processing of HTML while inserting and reading from database. This blocks wrapping within <p> tags.

The Event Listener

The Listener looks like this:



namespace E2\E2Core\EventListener;

use TYPO3\CMS\RteCKEditor\Form\Element\Event\AfterPrepareConfigurationForEditorEvent;

 * Transports some of the TCA features into RTE.
 * RTE can limit input based on a count, just like TCA 'max' property.
class TcaToRteConfiguration
    public function __invoke(AfterPrepareConfigurationForEditorEvent $event): void
        $rteConfiguration = $event->getConfiguration();
        $fieldConfiguration = $event->getData()['parameterArray']['fieldConf']['config'] ?? [];

        $rteConfiguration = $this->setRows($rteConfiguration, $fieldConfiguration);
        $rteConfiguration = $this->setMax($rteConfiguration, $fieldConfiguration);


    private function setRows(array $rteConfiguration, array $fieldConfiguration): array
        $rows = $fieldConfiguration['rows'] ?? 0;

        if ($rows > 0) {
            $rteConfiguration['height'] = ($rows * 6) . 'rem';

        return $rteConfiguration;

    private function setMax(array $rteConfiguration, array $fieldConfiguration): array
        $max = $fieldConfiguration['max'] ?? 0;

        if ($max > 0) {
            $rteConfiguration['wordcount']['maxCharCount'] = (int) $max;

        return $rteConfiguration;

And is registered like this (within Services.yaml of the extension):

    autowire: true
    autoconfigure: true
    public: false

    resource: '../Classes/*'

      - name: 'event.listener'
        event: 'TYPO3\CMS\RteCKEditor\Form\Element\Event\AfterPrepareConfigurationForEditorEvent'

Combining the pieces

We need to properly configure our TCA column to use the dedicated configuration. The column looks like this:

'tx_e2core_link_label_label' => [
    'label' => $languagePath . 'tx_e2core_link_label_label',
    'config' => [
        'type' => 'text',
        'eval' => 'required,trim',
        'max' => 255,
        'rows' => 1,
        'enableRichtext' => true,
        'richtextConfiguration' => 'minimal-input-field',

This converts our input to a text field. It is still required and gets trimmed. The max and rows are respected via above EventListener. The last two turn the field into an RTE with our dedicated configuration.

The RTE configuration itself is registered within ext_localconf.php:

        'RTE' => [
            'Presets' => [
                'default' => 'EXT:e2_core/Configuration/RTE/Editor/Custom.yaml',
                'minimal-input-field' => 'EXT:e2_core/Configuration/RTE/Editor/MinimalInputField.yaml',

We prefer the merge way as we don't have different ways to configure the $GLOBALS['TYPO3_CONF_VARS']. It is always this way within AdditionalConfiguration.php, LocalConfiguration.php and ext_localconf.php. That allows to copy and paste without adjusting the code.

Our Takeaway

We first thought there must be an extension or we should build an extension. That one should provide a new renderType for TCA input columns. We knew many others have the same issue and one of them should have already done that.
But we didn't find an extension and thought there should be an easier way and came up with our solution. That one is so flexible and easy to integrate that it doesn't make sense to provide an extension but a blog post. Every installation and even some fields have very special needs which now can be covered with different configurations.

We love flexible and simple solutions as they are the best solutions most of the time. To us, it is important to overthink solutions and approaches from the past. It is also critical to not get driven by technology hype or by the feeling to release another extension. Find a proper solution for the actual problem, ignoring other influences from the outside. It is still possible to share those solutions. Either as blog post, video or a small gist or some other way.


Thanks to my co-worker Justus Moroni who once more helped to provide a good solution for a problem.

Thanks to our customer reuter.de who allows us to re-think existing solutions in order to improve editor UX.

Thanks to Codappix GmbH for allowing me to share our solutions on my own blog during working hours.

Further reading