How do you use type=inline in TYPO3 to create repeating fields?

1.3k views Asked by At

In TYPO3 I want to make an element that allows the user to create multiple sub-blocks within it. For example:

Create New +
|
|- Sub Block
|  |- Assets
|  |- Text Field
|
|- Sub Block
|  |- Assets
|  |- Text Field

From what I understand this is done using type='inline'

However the documentation assumes you know all previous steps of the process, and I have found no tutorials on this kind of element.

2

There are 2 answers

9
Mikel Wohlschlegel On BEST ANSWER

To add a new content element with a 1:n relation to a new record (not content element), you have to add a new record and a new property of tt_content describing the relation between tt_content and your record.

  1. Add a new table for your new record
  2. Add TCA for your new record
  3. Allow record to be added in default pages
  4. Extend table tt_content
  5. Add TCA for your new content element

As a basic example, I create a new record "my_list_item" and a new content element "my_list":

Add new table for your new record (ext_tables.sql):

CREATE TABLE tx_myext_domain_model_mylistitem (

    parent_uid int(11) DEFAULT '0' NOT NULL,
    parent_table varchar(255) DEFAULT '' NOT NULL,
    title varchar(255) DEFAULT '' NOT NULL

);

Describe new record in TCA (Configuration/TCA/tx_myext_domain_model_mylistitem.php

<?php
return [
    'ctrl' => [
        'title' => 'Label',
        'label' => 'title',
        'tstamp' => 'tstamp',
        'crdate' => 'crdate',
        'cruser_id' => 'cruser_id',
        'sortby' => 'sorting',
        'versioningWS' => true,
        'languageField' => 'sys_language_uid',
        'transOrigPointerField' => 'l10n_parent',
        'transOrigDiffSourceField' => 'l10n_diffsource',
        'delete' => 'deleted',
        'hideTable' => true,
        'enablecolumns' => [
            'disabled' => 'hidden',
        ],
        'searchFields' => 'title',
    ],
    'interface' => [
        'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, title',
    ],
    'columns' => [
        'sys_language_uid' => [
            'exclude' => true,
            'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
            'config' => [
                'type' => 'select',
                'renderType' => 'selectSingle',
                'special' => 'languages',
                'items' => [
                    [
                        'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
                        -1,
                        'flags-multiple'
                    ]
                ],
                'default' => 0,
            ],
        ],
        'l10n_parent' => [
            'displayCond' => 'FIELD:sys_language_uid:>:0',
            'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
            'config' => [
                'type' => 'select',
                'renderType' => 'selectSingle',
                'default' => 0,
                'items' => [
                    ['', 0],
                ],
                'foreign_table' => 'tx_myext_domain_model_mylistitem',
                'foreign_table_where' => 'AND {#tx_myext_domain_model_mylistitem}.{#pid}=###CURRENT_PID### AND {#tx_myext_domain_model_mylistitem}.{#sys_language_uid} IN (-1,0)',
            ],
        ],
        'l10n_diffsource' => [
            'config' => [
                'type' => 'passthrough',
            ],
        ],
        't3ver_label' => [
            'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.versionLabel',
            'config' => [
                'type' => 'input',
                'size' => 30,
                'max' => 255,
            ],
        ],
        'hidden' => [
            'exclude' => true,
            'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.visible',
            'config' => [
                'type' => 'check',
                'renderType' => 'checkboxToggle',
                'items' => [
                    [
                        0 => '',
                        1 => '',
                        'invertStateDisplay' => true
                    ]
                ],
            ],
        ],
        'title' => [
            'exclude' => true,
            'label' => 'Your header label',
            'config' => [
                'type' => 'input',
                'size' => 30,
                'eval' => 'trim,required'
            ],
        ],
        'parent_uid' => [
            'config' => [
                'type' => 'select',
                'renderType' => 'selectSingle',
                'items' => [
                    [
                        '',
                        0,
                    ],
                ],
                'default' => 0,
                'foreign_table' => 'tt_content',
                'foreign_table_where' => 'AND tt_content.pid=###CURRENT_PID### AND tt_content.sys_language_uid IN (-1, ###REC_FIELD_sys_language_uid###)',
            ],
        ],
        'parent_table' => [
            'config' => [
                'type' => 'passthrough',
            ],
        ],
    ],
    'types' => [
        '1' => ['showitem' =>
            '--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general, title, bodytext, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, sys_language_uid, l10n_parent, l10n_diffsource, --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, hidden'
        ],
    ],
];

Allow record on pages (ext_tables.php):

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages('tx_myext_domain_model_mylistitem');

Describe the TCA of the new record with the relation to itself (Configuration/TCA/Overrides/tt_content.php)

$myListItemTca = [
    'tx_myext_mylist' => [
        'exclude' => true,
        'label' => 'Field label',
        'config' => [
            'appearance' => [
                'collapseAll' => '1',
                'enabledControls' => [
                    'dragdrop' => '1',
                ],
                'levelLinksPosition' => 'bottom',
                'useSortable' => '1',
            ],
            'foreign_field' => 'parent_uid',
            'foreign_table' => 'tx_myext_domain_model_mylistitem',
            'foreign_table_field' => 'parent_table',
            'maxitems' => '20',
            'minitems' => '1',
            'type' => 'inline',
        ],
    ],
];

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns(
    'tt_content',
    $myListItemTca
);

Extend tt_content (ext_tables.sql)

CREATE TABLE tt_content (
    tx_myext_mylist int(11) unsigned DEFAULT '0' NOT NULL,
);

Add a new content element (Configuration/TCA/Overrides/tt_content.php):

$GLOBALS['TCA']['tt_content']['palettes']['mylist'] = array(
    'showitem' =>
        'tx_myext_mylist; Label',
    'canNotCollapse' => 1
);

$GLOBALS['TCA']['tt_content']['types']['mylist'] = array(
    'showitem' => '
        --div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:general,
            --palette--;;general,
            --palette--;;headers,
            --palette--;Label;mylist,
    ',
);

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem(
    'tt_content',
    'CType',
    [
        'Title',
        'mylist',
    ],
    'textmedia',
    'after'
);

This is just a basic example, reduced and replaced names from a working example I made a few weeks ago. Should I missed something, comment.

BTW: This is the same way which mask / mask exports handles repeatable elements. So of course you can also use mask export and clean the generated code for your own purpose (the code is of mask export is good and usable, but there is a bit overhead, as it must be more generic)

2
Bernd Wilke πφ On

You can use the extensions mask and mask_export to generate an extension for your kind of content element.

They handle everything for you from table enhancement to table declaration, with all code in mySQL and PHP (including TCA, getter/setter, ...).


If you want to do it by your own have a look in the documentation:

  1. How to define own content elements
  2. How to define TCA inline elments