xima / xima-typo3-recordlist
This package provides an abstract class for creating TYPO3 backend modules that display a feature-rich and easy-to-customize list view of records. It also includes built-in simplified TYPO3 workspace integration.
Installs: 8 082
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 6
Forks: 0
Open Issues: 5
Language:JavaScript
pkg:composer/xima/xima-typo3-recordlist
Requires
- php: ^8.2
- phpoffice/phpspreadsheet: *
- typo3/cms-core: ^13.4 || ^14.0
Requires (Dev)
- armin/editorconfig-cli: ^2.1
- bk2k/bootstrap-package: ^16.0
- ergebnis/composer-normalize: ^2.45
- friendsofphp/php-cs-fixer: ^3.12
- georgringer/news: ^14.0
- helmich/typo3-typoscript-lint: ^3.3
- move-elevator/composer-translation-validator: ^1.3
- phpstan/extension-installer: ^1.3
- roave/security-advisories: dev-latest
- symfony/translation: ^7.2
- typo3/cms-filelist: ^13.4 || ^14.0
- typo3/cms-lowlevel: ^13.4 || ^14.0
- typo3/cms-setup: ^13.4 || ^14.0
- typo3/cms-workspaces: ^13.4 || ^14.0
Suggests
- typo3/cms-workspaces: For workspace integration
- web-vision/deepltranslate-core: For DeepL integration
- dev-master
- v14.x-dev
- 14.0.0
- v13.x-dev
- 13.1.1
- 13.1.0
- 13.0.0
- v12.x-dev
- 12.0.5
- 12.0.4
- 12.0.3
- 12.0.2
- 12.0.1
- 12.0.0
- 11.0.0
- dev-acceptance-tests
- dev-method-di
- dev-category-tree
- dev-sorting-dropdown
- dev-language-validation
- dev-allow-skipping-workspace-stages
- dev-v13-refactoring
- dev-category-column
- dev-add-workspace-states
- dev-js-include
- dev-workspace-preview-2
- dev-workspace-preview
- dev-feature-kmi
- dev-additional-header-button
- dev-additional-html-to-recordlist
This package is auto-updated.
Last update: 2026-02-05 00:59:13 UTC
README
TYPO3 Recordlist
Quickly create feature-rich TYPO3 backend modules for managing records
This extension provides a powerful abstract controller for creating advanced record listing backend modules in TYPO3. Save development time
by extending AbstractBackendController instead of building record lists from scratch.
Table of Contents
- Why Use This Extension?
- Features
- Requirements
- Install
- Quick Start
- Customization
- Documentation
- Contributing
Why Use This Extension?
Building custom backend modules for listing and managing records typically requires significant boilerplate code. This extension eliminates that overhead by providing:
- Rapid Development: Get a fully-functional backend module with just a few lines of code
- Rich Features Out-of-the-Box: Filtering, sorting, pagination, inline editing, and more
- Multiple Table Support: Manage related tables in a single module with automatic table switching
- Workspace Integration: Built-in support for TYPO3 workspaces with simplified approval workflows
- Highly Customizable: Override templates, modify queries, add custom columns, and extend behavior
Features
- List records from any TYPO3 table
- Filter records by any field with customizable filters
- Sort records by any column
- Configurable columns with user-customizable visibility and order
- Inline editing for quick record updates
- Multiple tables in a single module with dropdown selection
- Multiple templates with per-template action control
- Workspace integration for content approval workflows
- Pagination for handling large datasets
- View record button linking to frontend preview
- Row selection with checkbox, row click, and keyboard shortcuts (Shift+Click, Ctrl/Alt+Click)
- Batch field editing from column headers for selected or all records
Requirements
- TYPO3 13.4+ or 14.0+
- PHP 8.2+
Install
composer require xima/xima-typo3-recordlist
Quick Start
Get a working backend module in 3 simple steps:
1. Extend new controller from AbstractBackendController
The controller implements the BackendControllerInterface which requires you to add the
methods getTableNames() and getRecordPid():
<?php // EXT:my_extension/Classes/Controller/UserController.php namespace Vendor\MyExtension\Controller\Backend; use Xima\XimaTypo3Recordlist\Controller\AbstractBackendController; class UserController extends AbstractBackendController { public function getTableNames(): array { return ['fe_users']; } public function getRecordPid(): int { return $this->site->getConfiguration()['userPid'] ?? 0; } }
Note: For multiple tables in one module, return multiple table names:
public function getTableNames(): array { return ['be_users', 'be_groups', 'sys_filemounts']; }
2. Register Backend Module
Register your module using
the Backend module API.
The key setting is controllerActions, which must reference your controller:
<?php // EXT:my_extension/Configuration/Backend/Modules.php use Vendor\MyExtension\Controller\Backend\UserController; return [ 'my_extension_users' => [ 'parent' => 'web', 'position' => ['after' => 'list'], 'access' => 'user', 'iconIdentifier' => 'content-text', 'workspaces' => '*', 'labels' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang_module.xlf', 'extensionName' => 'MyExtension', 'controllerActions' => [ UserController::class => [ 'processRequest', // Required action ], ], 'inheritNavigationComponentFromMainModule' => false, ], ];
3. Configure Template Path
Add the template path to your sitepackage using TSconfig:
# EXT:my_extension/Configuration/page.tsconfig
templates.vendor/my-extension.1740563365 = xima/xima-typo3-recordlist:Resources/Private/
That's it! Your backend module is now ready to use. Open the TYPO3 backend and navigate to your new module to see it in action.
💡 Tip: Check out the Example directory for working implementations including single-table and multi-table modules.
Customization
The extension is highly customizable through method overrides in your controller. Here are the most common customization options:
Templates
Override templates, partials, or sections by configuring an additional template path in your TSconfig:
# EXT:my_extension/Configuration/page.tsconfig
templates.vendor/my-extension.1740570140 = my-vendor/my-extension:Resources/Private/TemplateOverrides
Inside your TemplateOverrides folder, create a Templates directory, copy the Default.html
file, and customize it.
Custom Template Configurations
By default, there is only one template (Default) available. If you define multiple templates, the template selection appears automatically
in the View dropdown and the selection is persisted. To define which templates are available, override getTemplateConfigurations():
class NewsController extends AbstractBackendController { protected function getTemplateConfigurations(): array { return [ 'Default' => [ 'title' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:template.list', 'icon' => 'actions-list', ], 'Cards' => [ 'title' => 'LLL:EXT:my_extension/Resources/Private/Language/locallang.xlf:template.cards', 'icon' => 'actions-menu', 'actions' => ['templateSelection', 'newRecord'], // Only show template switcher and new record button ], ]; } }
Create corresponding template files (e.g., Default.html, Cards.html) in your Templates directory.
Configuration Options:
| Key | Description |
|---|---|
title |
Template label (supports LLL: references) |
icon |
TYPO3 icon identifier for the dropdown |
actions |
Array of enabled actions for this template |
Available Actions:
Setting actions limits which actions are shown in the module header for the selected template.
| Action | Description |
|---|---|
templateSelection |
Template switcher in View dropdown |
showColumns |
Column selector in View dropdown |
download |
Download button |
toggleSearch |
Search toggle button |
tableSelection |
Table selection menu |
pidSelection |
Page selection menu |
languageSelection |
Language selection menu |
newRecord |
New record button |
Table-Specific Templates:
For controllers managing multiple tables, return different templates per table:
protected function getTemplateConfigurations(): array { $tableName = $this->getTableName(); return match ($tableName) { 'tx_news_domain_model_news' => [ 'Default' => ['title' => 'News List', 'icon' => 'actions-list'], 'Cards' => ['title' => 'News Cards', 'icon' => 'actions-menu'], ], 'tx_news_domain_model_tag' => [ 'Default' => ['title' => 'Tag List', 'icon' => 'actions-list'], ], default => [ 'Default' => ['title' => 'List', 'icon' => 'actions-list'], ], }; }
Modifying Records
Add computed fields or transform data by overriding the modifyRecord() method:
class UserController extends AbstractBackendController { protected function modifyRecord(array &$record): void { // Add computed field $record['fullName'] = $record['first_name'] . ' ' . $record['last_name']; // Format date $record['formatted_date'] = date('Y-m-d', $record['crdate']); } }
Custom Filters
Add custom filter options by modifying the query builder:
class UserController extends AbstractBackendController { protected function modifyQueryBuilder(): void { $body = $this->request->getParsedBody(); // Add custom date filter if (!empty($body['register_date'])) { $registerDate = new \DateTime($body['register_date']); $this->additionalConstraints[] = $this->queryBuilder->expr()->gte( 'register_date', $registerDate->getTimestamp() ); } // Add custom status filter if (!empty($body['status'])) { $this->additionalConstraints[] = $this->queryBuilder->expr()->eq( 'status', $this->queryBuilder->createNamedParameter($body['status']) ); } } }
Column Configuration
Configure Default Columns
Set which columns appear by default and in what order:
class NewsController extends AbstractBackendController { protected function modifyTableConfiguration(): void { $this->tableConfiguration['your-table-name']['columns']['fal_media']['defaultPosition'] = 2; $this->tableConfiguration['your-table-name']['columns']['author']['defaultPosition'] = 3; $this->tableConfiguration['your-table-name']['columns']['sitemap_changefreq']['defaultPosition'] = 4; $this->tableConfiguration['your-table-name']['columns']['sys_language_uid']['defaultPosition'] = 5; $this->tableConfiguration['your-table-name']['columns']['workspace-status']['defaultPosition'] = 6; } }
Fixed Columns
The extension provides two fixed columns that appear before configurable columns:
- Checkbox Column: Enables row selection for batch operations
- Icon Column: Displays the record type icon with automatic language indentation
Both columns can be disabled per table:
class FilesController extends AbstractBackendController { protected function modifyTableConfiguration(): void { // Hide icon column $this->tableConfiguration['sys_file_metadata']['showIconColumn'] = false; // Hide checkbox column $this->tableConfiguration['sys_file_metadata']['showCheckboxColumn'] = false; } }
Special Columns
The extension automatically adds special columns that users can enable via the column selector:
- UID Column: Displays the unique record ID
- PID Column: Displays the page ID where the record is stored
- Workspace Status Column: Shows workspace state (when workspace mode is active)
These columns are disabled by default but can be activated:
class NewsController extends AbstractBackendController { protected function modifyTableConfiguration(): void { // Show UID column by default $this->tableConfiguration['tx_news_domain_model_news']['columns']['uid']['active'] = true; $this->tableConfiguration['tx_news_domain_model_news']['columns']['uid']['defaultPosition'] = 2; // Show PID column by default $this->tableConfiguration['tx_news_domain_model_news']['columns']['pid']['active'] = true; $this->tableConfiguration['tx_news_domain_model_news']['columns']['pid']['defaultPosition'] = 3; } }
Enable Inline Editing
Make specific columns editable inline by assigning a partial:
class UserController extends AbstractBackendController { protected function modifyTableConfiguration(): void { // Enable inline editing for title field $this->tableConfiguration['your-table-name']['columns']['title']['partial'] = 'TextInlineEdit'; // Enable inline editing for description $this->tableConfiguration['your-table-name']['columns']['description']['partial'] = 'TextInlineEdit'; } }
Custom Actions
Adding View/Preview Actions
The view button is automatically displayed if TCEMAIN.preview is configured for your table.
To manually add view URLs:
class UserController extends AbstractBackendController { protected function modifyPaginatedRecords(): void { parent::modifyPaginatedRecords(); foreach ($this->records as &$record) { // Add custom frontend URL $record['url'] = 'https://example.com/user/' . $record['uid']; } } }
Documentation
- 📋 Changelog - See what's new in each version
- 🔄 Migration Guide - Upgrading from 13.x to 14.x
- 📁 Example Controllers - Working implementation examples
Contributing
Contributions are welcome! See CONTRIBUTING.md for development setup and guidelines.
License
This extension is licensed under GPL-2.0-or-later.
Credits
Developed and maintained by XIMA Media GmbH.
Found this extension helpful? Please star ⭐ the repository!
