Contao offers numerous possibilities for content creation. The respective advantages and disadvantages can be helpful when weighing and selecting. As an example here is the implementation of a »front end filter«:
The animated filtering of arbitrary contents is often used to display e.g. references without having to reload the website. The contents to be filtered must first be assigned to appropriate categories. Subsequently, the presentation can be influenced specifically via these categories.
For our request you can use the extension codefog/contao-elements-filter for example. You can find more information on the author’s GitHub page.
Pro:
A Contao extension performs a special task, is mostly free of charge and can be easily
installed. You do not have to worry about the actual technical implementation. The editing for you or other editors is
easily done using the well-known Contao input options. Documentation, especially for free extensions, is usually done
via the corresponding GitHub pages. Alternatively, you can find helpful support via the community in the
Contao forum.
Contra:
If you update Contao or change the PHP version, it might happen that the extension is not yet ready for this. In this
case you have to rely on the author’s modifications. Especially if you get a free offer, you will get help from the
Contao community too.
Known JavaScript solutions for our requirements are e.g. Isotopes or MixItUp. In case of a commercial use the purchase of licenses is necessary. For our example we use the open source solution Filterizr.
Examples and documentation can be found on the Filterizr website and on GitHub. The solution can be implemented either as »jQuery Plugin« or as »Vanilla JS«. We use the latter in the following.
After the download you will find the directory »dist« with the file »vanilla.filterizr.min.js« in the zip archive. Copy this file into a public directory of your Contao installation below »files«.
For the »Filterizr« script, the content to be filtered must be declared with the CSS class filtr-item
. The category
assignment is done via a HTML5 data attribute data-category
. An exemplary HTML structure could look like the following
and must be mapped within Contao:
<ul>
<li data-filter="all">All animals</li>
<li data-filter="Dog">Dogs only</li>
<li data-filter="Cat">Cats only</li>
</ul>
<div class="filter-container">
<div class="filtr-item" data-category="Dog">
<img src="sample1.jpg" />
</div>
<div class="filtr-item" data-category="Cat">
<img src="sample2.jpg" />
</div>
</div>
<script type="text/javascript" src="files/MyPathToFile/vanilla.filterizr.min.js"></script>
<script>const filterizr = new Filterizr('.filter-container');</script>
The above HTMl structure can be created with Contao’s own content elements. We use the content element of type »HTML« for the HTML blocks and one or more elements of type »Text« for the actual content. The implementation in the Contao backend would therefore be:
The only thing missing is the assignment of our categories via the HTML5 data attribute. In the content element of type »Text« this input option is missing. We can realize this by using customized Contao templates.
When certain conventionally defined specifications are entered in the »Expert settings CSS-ID/Class« section, these
are to be output as HTML5 data attributes via the template. When entering filtr-item DATA-dog
in the CSS class area, we
want to achieve the following output:
...
<div class="ce_text filtr-item block" data-category="Dog">
...
Create two new templates based on »ce_text.html5« and »block_searchable.html5« in the template directory you specified under »Themes«.
For example as »ce_text_filter.html5« and »block_searchable_filter.html5« and use the new template »ce_text_filter.html5« in your content elements of type »text« to be filtered.
// ce_text_filter.html5
<?php $this->extend('block_searchable_filter'); ?>
<?php $this->block('content'); ?>
<?php if (!$this->addBefore): ?>
<?= $this->text ?>
<?php endif; ?>
<?php if ($this->addImage): ?>
<?php $this->insert('image', $this->arrData); ?>
<?php endif; ?>
<?php if ($this->addBefore): ?>
<?= $this->text ?>
<?php endif; ?>
<?php $this->endblock(); ?>
// block_searchable_filter.html5
<?php
$strDelimiter = "DATA-";
$strPattern = '/'.$strDelimiter.'(.+?)\b/i';
$strDataAttr = "data-category";
$strCSS = $this->class;
if ( substr_count($strCSS, $strDelimiter) > 0 ) {
preg_match_all($strPattern, $strCSS, $arrMatches, PREG_PATTERN_ORDER, 0);
for( $i = 0; $i <= count($arrMatches); $i++) {
$strCSS = str_replace($arrMatches[0][$i], "", $strCSS);
$arrMatchedValues[] = $arrMatches[1][$i];
}
$strData = $strDataAttr.'="'.rtrim(implode(", ", $arrMatchedValues), ", ").'"';
}
?>
<div class="<?= $strCSS ?> block"<?= $strData ?><?= $this->cssID ?><?php if ($this->style): ?> style="<?= $this->style ?>"<?php endif; ?>>
<?php $this->block('headline'); ?>
<?php if ($this->headline): ?>
<<?= $this->hl ?>><?= $this->headline ?></<?= $this->hl ?>>
<?php endif; ?>
<?php $this->endblock(); ?>
<?php $this->block('content'); ?>
<?php $this->endblock(); ?>
</div>
The script expects the contents within a HTML block <div class="filter-container">...</div>
. For a clearer backend
display, you could use the Contao Accordeon elements
»Envelope start« and »Envelope end« for other purposes. In the element »Envelope start« you then use the CSS class
»filter-container«.
Furthermore, for simplicity’s sake, we have entered the JavaScript references directly in the content element.
Alternatively, you could also store them as JavaScript Asset in the template.
Pro:
You don’t have to rely on extensions and you have complete control over the implementation and maintenance. For Contao
updates, you might only have to consider possible changes to the core templates.
Contra:
For template adjustments in this form, at least rudimentary PHP knowledge is required. The
Contao community will help you with these questions. The use of HTML5 data attributes
is not obvious to editors and requires documentation.
For the next example, we take over the previous implementation via the content elements. For the input of the HTML5 data attributes, however, we will create a new, additional input field for the content element of type »Text« and extend the Contao Data Container Array (DCA) for this purpose.
In the developer documentation you can find an example of Contao
DCA manipulation. The Contao file »tl_content.php« and the corresponding database table tl_content
is responsible for the content elements:
If not already there, create a new directory »contao/dca« in your Contao root directory with a file »tl_content.php«:
// contao/dca/tl_content.php
use Contao\CoreBundle\DataContainer\PaletteManipulator;
$GLOBALS['TL_DCA']['tl_content']['fields']['myCustomDataAttributes'] = [
'label' => ['Data-Attribut', 'Set your Html Data-Attribut.'],
'inputType' => 'keyValueWizard',
'default' => serialize([['key' => 'data-category']]),
'eval' => ['tl_class' => 'w50'],
'exclude' => true,
'sql' => "text NULL",
];
PaletteManipulator::create()
->addLegend('Settings Data-Attribut', 'expert_legend', PaletteManipulator::POSITION_AFTER)
->addField('myCustomDataAttributes', 'Settings Data-Attribut', PaletteManipulator::POSITION_APPEND)
->applyToPalette('text', 'tl_content')
;
In order for Contao to take over this information, you have to update the »application cache« in the »System maintenance« section of the Contao Manager. Then call the Contao installation tool. The tool recognizes the new field and offers you to create it in the database table »tl_content«. Every time you change the file »contao/dca/tl_content.php« this will be necessary again.
The content element of type »Text
« now contains a new input field (As key/value pair) for our data-attributes below
the »Expert settings«. For example to specify »data-category
« in the field »Key« and an entry »Dog
« in the field »Value«.
For the output on the website we have to adapt the template files again. Analogous to the previous example we use the
two template files »ce_text_filter.html5
« and »block_searchable_filter.html5
«.
// ce_text_filter.html5
<?php $this->extend('block_searchable_filter'); ?>
<?php $this->block('content'); ?>
<?php if (!$this->addBefore): ?>
<?= $this->text ?>
<?php endif; ?>
<?php if ($this->addImage): ?>
<?php $this->insert('image', $this->arrData); ?>
<?php endif; ?>
<?php if ($this->addBefore): ?>
<?= $this->text ?>
<?php endif; ?>
<?php $this->endblock(); ?>
// block_searchable_filter.html5
<?php if ($this->myCustomDataAttributes) {
$dataAttributesString = "";
$dataAttributes = \StringUtil::deserialize($this->myCustomDataAttributes);
$parsedDataAttributes = [];
foreach ($dataAttributes as $index=>$dataAttribute) {
$parsedDataAttributes[] = 'data-' . str_replace('data-', '', $dataAttribute['key'])
. '="' . $dataAttribute['value']
. '"';
}
$dataAttributesString = implode(' ' , $parsedDataAttributes);
}
?>
<div class="<?= $this->class ?> block"<?= $this->cssID ?><?php if ($this->style): ?> style="<?= $this->style ?>"<?php endif; ?> <?= $dataAttributesString ?>>
<?php $this->block('headline'); ?>
<?php if ($this->headline): ?>
<<?= $this->hl ?>><?= $this->headline ?></<?= $this->hl ?>>
<?php endif; ?>
<?php $this->endblock(); ?>
<?php $this->block('content'); ?>
<?php $this->endblock(); ?>
</div>
Pro:
You have complete control over the implementation and maintenance. You and your editors can easily enter the required
information in input fields.
Contra:
Rudimentary knowledge of PHP and the well documented Contao DCA is required.
The Contao community will also help you with such questions.
The »RockSolid Custom Elements« (RSCE) is a Contao extension that allows you to create individual content elements and frontend modules with convenient input and output in Contao.
If you are wondering why another extension is presented in this context:
Pro:
You use three different extensions from different authors e.g. a »frontend filter«, an alternative »content slider« and
your favourite »photo gallery«. The more extensions you use, the more work you might have to do for future Contao updates.
By using »RSCE«, you limit this to one single extension and you can still allow yourself and your editors to easily
edit all three within Contao. Furthermore, the extension is maintained and kept up-to-date by
Martin Auswöger (@ausi / member of the Contao core team).
Contra:
Knowledge of the well documented Contao DCA is necessary. The Contao
community is also there to help you with such questions.
The »RSCE« extension is based on the existing Contao conventions. You only need two files that are created in the specified template directory of your theme. You can then edit and maintain them within Contao.
These files are a ».php« configuration file with Contao DCA information and a «.html5« template file for output. You have to consider the following convention for the file names:
The name of the template file must start with »rsce_«, the configuration file must have the same name as the template and additionally the suffix »_config«: For example »rsce_my_filter.html5« and »rsce_my_filter_config.php«.
// rsce_my_filter_config.php
return array(
'label' => array('Filter-Element', 'Frontend-Filter Content'),
'types' => array('content'),
'contentCategory' => 'texts',
'standardFields' => array('headline', 'text', 'image', 'cssID'),
'wrapper' => array(
'type' => 'none',
),
'fields' => array(
'description' => array(
'label' => array('Data-Attribut', 'Specification of one or more HTML Data attribute(s)'),
'inputType' => 'group',
),
'data' => array(
'label' => ['Data-Attribut:', 'Attribut-Name / Attribut-Value'],
'inputType' => 'keyValueWizard',
'default' => serialize([['key' => 'data-category']]),
'eval' => ['tl_class' => 'w50'],
),
),
);
// rsce_my_filter.html5
<?php if ($this->data){
$dataAttributesString = "";
$dataAttributes = $this->data;
$parsedDataAttributes = [];
foreach ($dataAttributes as $index=>$dataAttribute) {
$parsedDataAttributes[] = 'data-' . str_replace('data-', '', $dataAttribute['key'])
. '="' . $dataAttribute['value']
. '"';
}
$dataAttributesString = implode(' ' , $parsedDataAttributes);
}
?>
<div class="<?= $this->class ?> block" <?= $this->cssID ?> <?= $dataAttributesString ?>>
<?php if ($this->headline): ?>
<<?= $this->hl ?>><?= $this->headline ?></<?= $this->hl ?>>
<?php endif; ?>
<?php if ($this->addBefore): ?>
<?= $this->text ?>
<?php endif; ?>
<?php if ($this->addImage): ?>
<?php $this->insert('image', $this->arrData); ?>
<?php endif; ?>
<?php if (!$this->addBefore): ?>
<?= $this->text ?>
<?php endif; ?>
</div>
Here you can choose a new, own content element under the name »Filter-Element«. You can then use this for the content to be filtered in combination with the content elements of the type »HTML« (see above).
With the »RSCE« extension you could also create your own Envelope elements and use them instead of the previous content elements of type »HTML«.
The extension »MetaModels« follows a similar approach and does not confront you with a direct Contao »DCA configuration«. However, this extension goes far beyond the requirements that are necessary here. The learning curve (see documentation) is accordingly higher.
Contao offers many possibilities to meet your requirements. The way of implementation is always a balance between comfort and later update effort. Especially for client-side solutions that are only based on the interaction of HTML, CSS and Javascript, Contao provides a variety of solutions independent of existing extensions.