Feature: #99459 - Respect record type while creating new records 

See forge#99459

Description 

The "Create new record" component in the backend, which is accessible in the Content > List module, has been enhanced to automatically detect and display all available record types for tables that support sub-schemas (record types). This improvement simplifies creating specific record types and eliminates the need to change the type afterward in the editing form, which could previously lead to invalid record states being stored in the database.

The interface now features automatic record type detection. Tables with multiple record types are automatically expanded to show all available types in a collapsible dropdown interface.

The options to create new pages now also show the different page types ( doktype) as expandable options when creating new pages "inside" or "after" an existing page.

To disable direct creation of a specific record type, a new TCA option ['creationOptions']['enableDirectRecordTypeCreation'] is available at the record type level:

EXT:my_extension/Configuration/TCA/Overrides/pages.php
use TYPO3\CMS\Core\Domain\Repository\PageRepository´;

// Disable direct creation of shortcuts
$GLOBALS['TCA']['pages']['types'][(string)PageRepository::DOKTYPE_SHORTCUT]['creationOptions']['enableDirectRecordTypeCreation'] = false;
Copied!

Individual titles for each record type are automatically picked up from the type-specific title configuration in the types section (see Feature #108027), falling back to the select item label if no type-specific title is defined.

Additionally, the new PSR-14 event \TYPO3\CMS\Backend\Controller\Event\ModifyNewRecordCreationLinksEvent allows for complete customization of the creation links.

Impact 

For tables that support sub-schemas (multiple record types), the new record wizard automatically detects all available types and displays them in a collapsible interface. This includes:

  • All tables with TCA type fields (such as sys_file_collection or index_config)
  • The pages table with its different doktype values
  • Extension tables with custom record types

The ModifyNewRecordCreationLinksEvent provides complete control over the creation link structure, allowing extensions to:

  • Add custom record creation options
  • Modify existing groups and items
  • Override icons, labels, and URLs
  • Create entirely custom wizard interfaces

Data Structure 

The event works with a nested array structure representing grouped creation links:

[
    'content' => [
        'title' => 'Content',
        'icon' => '<img src="..." />',
        'items' => [
            'sys_file_collection' => [
                'label' => 'File Collection',
                'icon' => '<typo3-backend-icon ...>',
                'types' => [
                    'static' => [
                        'url' => '/typo3/record/edit?edit[sys_file_collection][1]=new&defVals[sys_file_collection][type]=static',
                        'icon' => '<typo3-backend-icon ...>',
                        'label' => 'Static File Collection'
                    ],
                    'folder' => [
                        'url' => '/typo3/record/edit?edit[sys_file_collection][1]=new&defVals[sys_file_collection][type]=folder',
                        'icon' => '<typo3-backend-icon ...>',
                        'label' => 'Folder from Storage'
                    ]
                ]
            ]
        ]
    ],
    'pages' => [
        'title' => 'Create New Page',
        'icon' => '<typo3-backend-icon ...>',
        'items' => [
            'inside' => [
                'label' => 'Page (inside)',
                'icon' => '<typo3-backend-icon ...>',
                'types' => [
                    '1' => [
                        'url' => '/typo3/record/edit?edit[pages][1]=new&defVals[pages][doktype]=1',
                        'icon' => '<typo3-backend-icon ...>',
                        'label' => 'Standard Page'
                    ],
                    '254' => [
                        'url' => '/typo3/record/edit?edit[pages][1]=new&defVals[pages][doktype]=254',
                        'icon' => '<typo3-backend-icon ...>',
                        'label' => 'Folder'
                    ]
                ]
            ]
        ]
    ]
]
Copied!

Event Listener Example 

The event provides access to:

  • $event->groupedCreationLinks - The complete structure of creation links
  • $event->pageTS - The current page's TSconfig array
  • $event->pageId - The current page ID
  • $event->request - The current server request object

This allows for comprehensive customization while maintaining backward compatibility with existing setups.

EXT:my_extension/Classes/EventListener/CustomizeNewRecordCreationLinksEventListener.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\EventListener;

use TYPO3\CMS\Backend\Controller\Event\ModifyNewRecordCreationLinksEvent;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\Attribute\AsEventListener;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Imaging\IconSize;

final readonly class CustomizeNewRecordWizardEventListener
{
    public function __construct(
        private IconFactory $iconFactory,
        private UriBuilder $uriBuilder,
    ) {}

    #[AsEventListener]
    public function __invoke(ModifyNewRecordCreationLinksEvent $event): void
    {
        // Add a custom creation group
        $customGroup = [
            'title' => 'Custom Records',
            'icon' => $this->iconFactory->getIcon('apps-pagetree-category')->render(),
            'items' => [
                'tx_myext_domain_model_item' => [
                    'url' => (string)$this->uriBuilder->buildUriFromRoute('record_edit', [
                        'edit' => ['tx_myext_domain_model_item' => [$event->pageId => 'new']],
                        'returnUrl' => $event->request->getAttribute('normalizedParams')->getRequestUri(),
                    ]),
                    'icon' => $this->iconFactory->getIconForRecord('tx_myext_domain_model_item', []),
                    'label' => 'Custom Item',
                ]
            ]
        ];

        // Add the custom group to the existing structure
        $event->groupedCreationLinks['custom'] = $customGroup;

        // Modify existing groups, for example, remove specific items
        if (isset($event->groupedCreationLinks['system']['items']['sys_template'])) {
            unset($event->groupedCreationLinks['system']['items']['sys_template']);
        }

        // Add custom types to an existing table
        if (isset($event->groupedCreationLinks['content']['items']['sys_note'])) {
            $event->groupedCreationLinks['content']['items']['sys_note']['types'] = [
                'important' => [
                    'url' => (string)$this->uriBuilder->buildUriFromRoute('record_edit', [
                        'edit' => ['sys_note' => [$event->pageId => 'new']],
                        'defVals' => ['sys_note' => ['category' => '1']],
                        'returnUrl' => $event->request->getAttribute('normalizedParams')->getRequestUri(),
                    ]),
                    'icon' => $this->iconFactory->getIcon('status-dialog-warning', IconSize::SMALL),
                    'label' => 'Important Note',
                ],
                'info' => [
                    'url' => (string)$this->uriBuilder->buildUriFromRoute('record_edit', [
                        'edit' => ['sys_note' => [$event->pageId => 'new']],
                        'defVals' => ['sys_note' => ['category' => '0']],
                        'returnUrl' => $event->request->getAttribute('normalizedParams')->getRequestUri(),
                    ]),
                    'icon' => $this->iconFactory->getIcon('status-dialog-information', IconSize::SMALL),
                    'label' => 'Information Note',
                ]
            ];
        }
    }
}
Copied!