Feature: #104974 - Content area related information in the frontend 

See forge#104974

Description 

Feature: #103504 - New ContentObject PAGEVIEW introduced the PAGEVIEW cObject for frontend rendering. It is a powerful alternative to the FLUIDTEMPLATE cObject, allowing a full page to be rendered with less configuration.

PAGEVIEW has now been extended and provides all content elements related to a page, grouped by their columns as defined in the page layout. The elements are provided as fully resolved Record objects (see Feature: #103783 - RecordTransformation Data Processor and Feature: #103581 - Automatically transform TCA field values for record objects).

The content elements are attached to the new \TYPO3\CMS\Core\Page\ContentArea object, which also contains all column-related information and configuration. This is useful for frontend rendering because an element may need to know its rendering context. Knowing this information, an element can, for example, decide not to render the Header partial if it is in a sidebar content area.

ContentArea objects are added to the view either by variable name defined in contentAs or, if not defined, content. Content elements can then be accessed via the records property.

ContentArea objects contain backend layout-related configuration, such as content restrictions. These allow further validation such as whether a content type is valid.

Therefore {content.main.records} can be used to get content elements from the main content area. main is the identifier as defined in the page layout, and content is the default variable name.

Accessing a ContentArea using {content.main} makes the following information available, as defined in the page layout:

  • identifier - The column identifier
  • colPos - The defined colPos
  • name - The descriptive name, which might be a locallang key
  • allowedContentTypes - The defined allowedContentTypes
  • disallowedContentTypes - The defined disallowedContentTypes
  • slideMode - The defined ContentSlideMode , which defaults to ContentSlideMode::None
  • configuration - The complete content area-related configuration
  • records - The content elements as Record objects

The following example renders the content elements of a page which has only a single column:

mod.web_layout.BackendLayouts {
  default {
    title = Default
    config {
      backend_layout {
        colCount = 1
        rowCount = 1
        rows {
          1 {
            columns {
              1 {
                name = Main Content Area
                colPos = 0
                identifier = main
              }
            }
          }
        }
      }
    }
  }
}
Copied!
page = PAGE
page.10 = PAGEVIEW
page.10.paths.10 = EXT:my_site_package/Resources/Private/Templates/
Copied!
<f:for each="{content.main.records}" as="record">
    <f:render partial="ContentElement"
              arguments="{record: record, area: content.main}" />
</f:for>
Copied!

The introduction of the new f:render.contentArea and f:render.record ViewHelpers means that manually iterating over content elements is no longer necessary. All the content elements in a content area can be rendered with a single ViewHelper call:

<!-- Tag syntax -->
<f:render.contentArea contentArea="{content.main}" />

<!-- Inline syntax -->
{content.main -> f:render.contentArea()}
Copied!

To render a single record, use the f:render.record ViewHelper:

<!-- Tag syntax -->
<f:render.record record="{content.main.records.0}" />

<!-- Inline syntax -->
{content.main.records.0 -> f:render.record()}
Copied!

Impact 

It is now possible to access all the content elements on a page, grouped by their column, as well as having all the column-related information and configuration available. In addition to reduced configuration effort, different rendering is possible for an element depending on context.

Example 

A content element template using a Default layout that renders the Header partial only if the content element is not in the sidebar column.

<f:layout name="Default" />

<f:section name="Main">
    <f:if condition="{area.identifier} != 'sidebar'">
        <f:render partial="Header" arguments="{_all}" />
    </f:if>

    <p>{record.text}</p>
    <f:image image="{record.image}" width="{area.configuration.imageWidth}" />
</f:section>
Copied!