Skip to content

Building content accordions in TYPO3 CMS

How to build content accordions with gridelements and without complicated code

Whenever it was necessary output content elements in a certain hierarchy I felt that the builtin options of TYPO3 are not intuitive to use. But with the help of the gridelements extension it's really easy to implement a simple hierarchy that is easy to maintain for the editor and does not require complicated TypoScript constructs.

The idea is to define a gridelements container that is a single row/column and just acts as a grouping container. Every content element in this container is rendered within the accordion.

The configuration of this container is very simple:

 

backend_layout {
colCount = 1
  rowCount = 1
  rows {
    1 {
      columns {
        1 {
          name = Content
          colPos = 0
          allowed = header,textmedia
        }
      }
    }
  }
}

A Fluid template is set for the container without any additional options (the number 1 is the ID of the CE Backend layout)

 

tt_content.gridelements_pi1.20.10.setup {
  1 < lib.gridelements.defaultGridSetup
  1 {
    cObject = FLUIDTEMPLATE
    cObject.file = EXT:yourextensionkey/Resources/Private/Extensions/gridelements/accordion.html
  }
}

The last remaining part is the Fluid template. The example template below generates the markup for a bootstrap accordion. A for loop iterates over all child content elements of the container and uses a VHS view helper (link to the documentation) to render the content element wrapped in the necessary divs.

 

<div id="c{data.uid}" class="row gridelement"
 xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
 xmlns:vhs="http://typo3.org/ns/FluidTYPO3/Vhs/ViewHelpers"
>
  <div class="col-xs-12">
     <div class="panel-group content-panel" id="accordion{data.uid}" role="tablist" aria-multiselectable="true">
       <f:for each="{data.tx_gridelements_view_children}" as="content">
         <div class="panel panel-default">
           <div class="panel-heading" role="tab" id="heading{content.uid}">
           <h3 class="panel-title">
             <a role="button" data-toggle="collapse" data-parent="#accordion{data.uid}" href="#collapse{content.uid}" aria-controls="collapse{content.uid}">
                {content.header}
<i class="glyphicon glyphicon-menu-down pull-right"></i>
               </a>
             </h3>
           </div>
           <div id="collapse{content.uid}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{content.uid}">
            <div class="panel-body">
             {vhs:content.render(contentUids: {0: content.uid})}
</div>
           </div>
         </div>
       </f:for>
     </div>
  </div>
</div>

I think this is a very simple and clean implementation that can be easily extended to all other scenarios where it's necessary to wrap content elements in a hierarchy. Another use case for this setup would be an image carousel or a tab representation of the content.

This information applies to TYPO3 CMS 7.

 

Update for CMS v8: Instead of the VHS viewhelper you may use gridelements information directly like:

 

<f:for each="{data.tx_gridelements_view_children}" as="content">
{data.tx_gridelements_view_child_{content.uid}->f:format.raw()}
</f:for>