List Module Integration
By default, TYPO3's Web > List module lists tt_content records the
same way it lists any other table: a flat list per colPos, with no
awareness that some of those rows are Grid Element children. Grid
Elements can instead nest a container's children under it in the List
module, with per-user expand and collapse state, but this is off by
default and must be enabled explicitly per project through the
nestingInListModule boolean extension configuration option
(disabled: 0).
What identifies a row's place in the list
As throughout Grid Elements, it is not colPos that the nested list
is built from, see Data Model. Two separate fields do that work,
and they stay distinct here exactly as they do everywhere else:
tx_gridelements_container, stored on the child, is the parent
Grid Element relation and is what determines which container a row is
nested under; tx_gridelements_columns, also stored on the child,
is the structural cell/column assignment within that container and is
what groups a container's children by cell once they are nested under
it. colPos still plays a role here, but only its own Core role:
every grid child carries colPos = -1 regardless of which container
or cell it belongs to, and that sentinel is what the query filtering
below uses to decide whether a row is a page-level, top-of-list record
or only appears nested inside its container's expanded row.
How the three pieces fit together
Once nestingInListModule is enabled, three separate mechanisms
combine to produce the nested list, none of them sufficient on its
own:
| Mechanism | Role |
|---|---|
ModifyDatabaseQueryForRecordListingListener
(PSR-14 event listener) | Adds colPos != -1 to the List module's base query for
tt_content, so grid children do not also appear as their
own top-level rows. |
Xclass\DatabaseRecordList /
Xclass\DatabaseRecordList12 | Renders each gridelements_pi1 container with an expand and
collapse control (contentCollapseIcon(), implemented on
Hooks\DatabaseRecordList and called directly, not through a
hook point) and, when expanded, lists its children indented
beneath it, grouped by tx_gridelements_columns. |
ModifyRecordListElementDataEvent /
ModifyRecordListElementDataListener | Dispatched per row by the XCLASS to attach the data the
template needs to know a row is expandable and to find its
children: _CONTAINER_COLUMNS_, _EXPANDABLE_,
_EXPAND_ID_, _EXPAND_TABLE_, _LEVEL_ and
_CHILDREN_. _CHILDREN_ itself is fetched through
GridElementsHelper::getChildren(), the same
tx_gridelements_container query used everywhere else in
Grid Elements, see Data Model. |
Why this needs an XCLASS at all
The query filtering and the per-row data are both handled through
PSR-14 events, consistent with the rest of Grid Elements, see
Extension Points. Building the actual nested,
expandable row output is not: TYPO3 Core's List module does not
currently expose an event or hook for restructuring how rows are
grouped and rendered relative to each other, only for adjusting query
conditions, header columns and per-row actions. XCLASSing
DatabaseRecordList is how Grid Elements reaches that part of the
rendering; it is the one place in the codebase this happens, and it
only takes effect for a project that has opted in, see
Extension Points for the caution around
extending it further.