For coders TYPO3 Tech Corner

Own content element in TYPO3 (image via sys_file_reference in FlexForm)

Own content element in TYPO3 (image via sys_file_reference in FlexForm)

In the example we use FlexForm to display custom fields. Of course it is debatable whether you want to add your own fields in the database table or whether you prefer to use FlexForm (we should examine the advantages and disadvantages in a separate blog post). In the example we want to render a new page content of the "Highlight" type as simply and quickly as possible. The design provides that in addition to texts, an image should also be displayed. In addition, the editor should be able to choose the background color and the structure.

Code Backend

You define a new content element via a TCA file in your site package, load a FlexForm file and define the fields to be displayed for this page content (EXT:in2template/Configuration/TCA/Overrides/tt_content.php):

<?php $languageFilePrefix = 'LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:'; $frontendLanguageFilePrefix = 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:'; /** * TCA manipulation (mainly for custom content elements) */ $tca = [ 'ctrl' => [ 'typeicons' => [ 'ce.highlight' => 'ce.highlight', ], 'typeicon_classes' => [ 'ce.highlight' => 'ce.highlight', ], ], 'types' => [ 'ce.highlight' => [ 'showitem' => '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general, --palette--;;general, header;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header.ALT.html_formlabel, pi_flexform, --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance, --palette--;;frames, --palette--;;appearanceLinks, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, --palette--;;language, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, --palette--;;hidden, --palette--;;access, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:categories, categories, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:notes, rowDescription, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:extended,' ], ], ]; $GLOBALS['TCA']['tt_content'] = array_replace_recursive($GLOBALS['TCA']['tt_content'], $tca); /** * Include Flexforms */ \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( '*', 'FILE:EXT:in2template/Configuration/FlexForms/ContentElements/Highlight.xml', 'ce.highlight' ); /** * Register custom content elements */ \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( 'tt_content', 'CType', [ 'LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:ce.highlight', 'ce.highlight', 'ce.highlight', ], 'textmedia', 'after' );

In the FlexForm file you define the fields to be displayed. Of particular interest is the image field, which is supposed to render IRRE datasets of the type sys_file_reference in the backend as usual (EXT:in2template/Configuration/FlexForms/ContentElements/Highlight.xml):

<T3DataStructure> <meta> <langDisable>1</langDisable> </meta> <sheets> <main> <ROOT> <TCEforms> <sheetTitle>LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.main</sheetTitle> </TCEforms> <type>array</type> <el> <title> <TCEforms> <label>LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.title</label> <config> <type>input</type> <eval>trim,required</eval> </config> </TCEforms> </title> <subtitle> <TCEforms> <label>LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.subtitle</label> <config> <type>text</type> <eval>trim</eval> </config> </TCEforms> </subtitle> <image> <TCEforms> <label>LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.image</label> <config> <type>inline</type> <maxitems>1</maxitems> <foreign_table>sys_file_reference</foreign_table> <foreign_table_field>tablenames</foreign_table_field> <foreign_label>uid_local</foreign_label> <foreign_sortby>sorting_foreign</foreign_sortby> <foreign_field>uid_foreign</foreign_field> <foreign_selector>uid_local</foreign_selector> <foreign_selector_fieldTcaOverride> <config> <appearance> <elementBrowserType>file</elementBrowserType> <elementBrowserAllowed>gif,jpg,jpeg,png,svg</elementBrowserAllowed> </appearance> </config> </foreign_selector_fieldTcaOverride> <foreign_types type="array"> <numIndex index="0"> <showitem>--palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,--palette--;;filePalette</showitem> </numIndex> <numIndex index="2"> <showitem>--palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,--palette--;;filePalette</showitem> </numIndex> </foreign_types> <foreign_match_fields> <fieldname>pi_flexform_highlight</fieldname> </foreign_match_fields> <appearance type="array"> <newRecordLinkAddTitle>1</newRecordLinkAddTitle> <headerThumbnail> <field>uid_local</field> <height>64</height> <width>64</width> </headerThumbnail> <enabledControls> <info>1</info> <new>0</new> <dragdrop>0</dragdrop> <sort>1</sort> <hide>0</hide> <delete>1</delete> <localize>1</localize> </enabledControls> <createNewRelationLinkTitle>LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference</createNewRelationLinkTitle> </appearance> <behaviour> <localizationMode>select</localizationMode> <localizeChildrenAtParentLocalization>1</localizeChildrenAtParentLocalization> </behaviour> <overrideChildTca> <columns type="array"> <uid_local type="array"> <config type="array"> <appearance type="array"> <elementBrowserType>file</elementBrowserType> <elementBrowserAllowed>jpg,jpeg,png,svg,gif</elementBrowserAllowed> </appearance> </config> </uid_local> </columns> <types type="array"> <numIndex index="2"> <showitem>alternative, title,--palette--;;filePalette</showitem> </numIndex> </types> </overrideChildTca> </config> </TCEforms> </image> <label> <TCEforms> <label>LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.label</label> <config> <type>input</type> <eval>trim</eval> </config> </TCEforms> </label> <link> <TCEforms> <exclude>1</exclude> <label>LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.link</label> <config type="array"> <type>input</type> <eval>trim</eval> <renderType>inputLink</renderType> </config> </TCEforms> </link> <background> <TCEforms> <exclude>1</exclude> <label>LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.background</label> <config> <type>select</type> <renderType>selectSingle</renderType> <items type="array"> <numIndex index="1" type="array"> <numIndex index="0">LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.background.0</numIndex> <numIndex index="1">0</numIndex> </numIndex> <numIndex index="2" type="array"> <numIndex index="0">LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.background.1</numIndex> <numIndex index="1">1</numIndex> </numIndex> </items> </config> </TCEforms> </background> <orient> <TCEforms> <exclude>1</exclude> <label>LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.orient</label> <config> <type>select</type> <renderType>selectSingle</renderType> <items type="array"> <numIndex index="1" type="array"> <numIndex index="0">LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.orient.0</numIndex> <numIndex index="1">0</numIndex> </numIndex> <numIndex index="2" type="array"> <numIndex index="0">LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:flexform.highlight.orient.1</numIndex> <numIndex index="1">1</numIndex> </numIndex> </items> </config> </TCEforms> </orient> </el> </ROOT> </main> </sheets> </T3DataStructure>

You may also want to have an entry in the wizard so that the new page content is prominently represented when you click on the plus symbol in the page module in the backend. This works via Page TSConfig - in our SitePackage at this point (EXT:in2template/Configuration/TsConfig/Page/Mod/Wizards/ContentElement.tsconfig):

mod.wizards.newContentElement.wizardItems { hfwu { header = Hochschule after = common show = * elements { highlight { iconIdentifier = ce.highlight title = LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:ce.highlight description = LLL:EXT:in2template/Resources/Private/Language/Backend/locallang.xlf:ce.highlight.description tt_content_defValues { CType = ce.highlight } } } } }

Code Frontend

So that the new element can also be rendered in the frontend, it needs a few lines of TypoScript (EXT:in2template/Configuration/TypoScript/Setup/ContentElements/Highlight.typoscript):

lib.in2templateContentElement =< lib.contentElement lib.in2templateContentElement { templateRootPaths { 20 = EXT:in2template/Resources/Private/Templates/ContentElements/ } partialRootPaths { 20 = EXT:in2template/Resources/Private/Partials/ContentElements/ } layoutRootPaths { 20 = EXT:in2template/Resources/Private/Layouts/ContentElements/ } } tt_content.ce\.highlight =< lib.in2templateContentElement tt_content.ce\.highlight { templateName = Highlight dataProcessing { 10 = TYPO3\CMS\Frontend\DataProcessing\FlexFormProcessor 20 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor 20 { references { table = tt_content fieldName = pi_flexform_highlight } as = image } } }

We use the already existing FlexFormProcessor (DataProcessor) from TYPO3, so that we can use the values from the FlexForm (actually as XML in the database) cleanly in the fluid. In addition, we also use the FilesProcessor so that we can conveniently use the related image to the page content in the template.

The associated HTML template can then look like this (EXT:in2template/Resources/Private/Templates/ContentElements/Highlight.html):

<div class="ce-disturber margin-top-m" id="c{data.uid}"> <div class="container"> <div class="disturber flex{f:if(condition:flexFormData.orient,then:' disturber--left')}{f:if(condition:flexFormData.background,then:' disturber--yellow')}"> <div class="flex__md-8"> <f:if condition="{image.0}"> <f:image image="{image.0}" class="disturber__image" width="900c" maxHeight="300" /> </f:if> </div> <div class="flex__md-4"> <h2 class="disturber__heading">{flexFormData.title}</h2> <f:if condition="{flexFormData.subtitle}"> <p>{flexFormData.subtitle -> f:format.nl2br()}</p> </f:if> <f:if condition="{flexFormData.link} && {flexFormData.label}"> <f:link.typolink class="disturber__button btn btn--primary margin-top-s" parameter="{flexFormData.link}">{flexFormData.label}</f:link.typolink> </f:if> </div> </div> </div> </div>

Remarks

Like most other posts on our blog, this snippet is not completely complete. For example, the entries in the language files (locallang.xlf) are still missing. We have not included the registered SVG icon in ext_localconf.php for reasons of space. We also assume that the user uses a site package so that his TYPO3 installation is properly configured.

Have fun integrating new elements into TYPO3

Back

"Code faster, look at the time" - does this sound familiar to you?

How about time and respect for code quality? Working in a team? Automated tests?

Join us