Joomla! World Conference 2026

Power to imagination! In Joomla 5.2, the brand new Articles Module was introduced, a super flexible module that enables you to showcase your articles. In this article, Viviana shows us how you can use this module to create an Advent Calendar. Get inspired and unleash your own creativity!

The Advent Calendar has a long tradition in Germany and in the last few years it has become popular in other countries too. Originally developed to help children to count the days before Christmas it has evolved to treat adults as well with sweets or small presents, one every day until Christmas. And of course there are also online advent calendars.

Some years ago there was an extension for Joomla to create advent calendars and I used it for several years for a client. An animal protection organization used the advent calendar to present nice stories, ask for help or introduce special pets. This extension is not being actively developed anymore and as another client asked me for an advent calendar for their website I had to look for a new solution. I wanted something lightweight that doesn’t need maintenance since it is a “once a year” requirement.

Joomla 5.2 introduced a new module, the Articles Module (internally known as “Content Module to Rule them All” - freely adapted from “The Lord of the Rings”). Five (of the seven) previous article modules have been combined to provide more flexibility (for more information see the help page: https://docs.joomla.org/Help5.x:Site_Modules:_Articles). I already use the module on new websites and I have also created some overrides for it. In this article I want to show you how I plan to implement an advent calendar for my client using the Articles module.

Preparation

To create the Advent Calendar, we need:

  • A category (I named it “Advent”)
  • A custom field from type Calendar for the articles (I first created a Field Group “Advent” and assigned the field named “Day” to the group and to the category). We will use this field to define which “door” in the advent calendar can be opened each day
  • 24 articles (e.g. Day 1, Day 2, …, Day 24) each of them with an intro image and an assigned day (Day 1 = 1st of December and so on). The content of the article can be whatever you want: a recipe, a poem, an image…

Screenshot custom field

Override

The Articles module consist of three files:

  • default.php
  • default_items.php
  • default_titles.php

Since I will use only a few parameters from the module I have created only one file named advent.php and rewrite the code to display a grid (6x4) containing only the intro images of the articles. The articles will be clickable when the assigned day matches today: Day 2 is assigned to the 2nd of December, the article can be seen before, but it will become clickable on December 2nd. The article will open on a modal window.

advent.php

<?php

/**
 * @package     Joomla.Site
 * @subpackage  mod_articles
 *
 * @copyright   (C) 2024 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
use Joomla\CMS\Router\Route;

/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $app->getDocument()->getWebAssetManager();
$wa->useScript('joomla.dialog-autocreate');

if (!$list) {
    return;
}

$items = $list;

$today = Factory::getDate()->format('Y-m-d');

// Set up the modal options that will be used for module editor
$popupOptions = [
    'popupType'  => 'iframe',
    'className'  => 'adventskalender',
];

?>

<div class="advent-grid">
    <?php foreach ($items as $item) : ?>
       <?php
            // Get the images for this article
            $images  = json_decode($item->images);

            // Get the custom fields for this article
            $jcfields = FieldsHelper::getFields('com_content.article', $item, true);

            // Create an associative array for easier access by field name
            foreach($jcfields as $jcfield) {
                $jcfields[$jcfield->name] = $jcfield;
            }

            // Ensure the field exists and is a valid date
            $openDay = isset($jcfields['day']) ? date('Y-m-d', strtotime($jcfields['day']->value)) : null;

            // Set up popup options
            $popupOptions['src'] = Route::_('index.php?option=com_content&view=article&id=' . $item->id . '&catid=' . $item->catid . '&layout=modal&tmpl=component', false);
            $popupOptions['textHeader'] = $item->title;

            $layoutAttr = [
                'src' => $images->image_intro,
                'alt' => empty($images->image_intro_alt) ? '' : $images->image_intro_alt,
            ];
        ?>
        <div class="mod-articles-advent-item-content">

            <?php if ($openDay <= $today) : ?>
            <button type="button"
                data-joomla-dialog="<?php echo htmlspecialchars(json_encode($popupOptions, JSON_UNESCAPED_SLASHES)) ?>"
                class="btn btn-link advent-link"
                aria-label="<?php echo $item->title; ?>"
                id="title-<?php echo $item->id; ?>"
                data-module-id="<?php echo $item->id; ?>">
                <figure class="advent-item-image">
                    <?php echo LayoutHelper::render('joomla.html.image', $layoutAttr); ?>
                </figure>
            </button>
            <?php else : ?>
                <figure class="advent-item-image">
                    <?php echo LayoutHelper::render('joomla.html.image', $layoutAttr); ?>
                </figure>
            <?php endif; ?>

        </div>
    <?php endforeach; ?>
</div>

Lines explained

With this line we get the script to create modal windows, this function is part of the Joomla core:

$wa->useScript('joomla.dialog-autocreate');

The module has the code to display the intro image of the article, but to avoid conflicts with other parameters one can have set for the website I decided to rewrite this part too. With this lines we get the images from the articles and set some attributes:

$images  = json_decode($item->images);
$layoutAttr = [
	'src' => $images->image_intro,
	'alt' => empty($images->image_intro_alt) ? '' : $images->image_intro_alt,
];

We also need the custom field:

$jcfields = FieldsHelper::getFields('com_content.article', $item, true);
            foreach($jcfields as $jcfield) {
                $jcfields[$jcfield->name] = $jcfield;
            }

These

// Set up the modal options that will be used for module editor
$popupOptions = [
    'popupType'  => 'iframe',
    'className'  => 'adventskalender',
];

and these

$popupOptions['src'] = Route::_('index.php?option=com_content&view=article&id=' . $item->id . '&catid=' . $item->catid . '&layout=modal&tmpl=component', false);
$popupOptions['textHeader'] = $item->title;

are options for the modal window. We use the title of the article as the title of the modal window.

We get the current date:

$today = Factory::getDate()->format('Y-m-d');

We check if the field exists and convert the value to the same date format:

$openDay = isset($jcfields['day']) ? date('Y-m-d', strtotime($jcfields['day']->value)) : null;

and compare the two values:

<?php if ($openDay <= $today) : ?>

Articles that are assigned to "today" or to earlier days become clickable with the help of a button around the image. Articles assigned to future days display only the image:

<?php if ($openDay <= $today) : ?>
<button type="button"
	data-joomla-dialog="<?php echo htmlspecialchars(json_encode($popupOptions, JSON_UNESCAPED_SLASHES)) ?>"
	class="btn btn-link advent-link"
	aria-label="<?php echo $item->title; ?>"
	id="title-<?php echo $item->id; ?>"
	data-module-id="<?php echo $item->id; ?>">
	<figure class="advent-item-image">
		<?php echo LayoutHelper::render('joomla.html.image', $layoutAttr); ?>
	</figure>
</button>
<?php else : ?>
	<figure class="advent-item-image">
		<?php echo LayoutHelper::render('joomla.html.image', $layoutAttr); ?>
	</figure>
<?php endif; ?>

CSS

I added the following CSS to the user.css from Cassiopeia:

.advent-grid {
    display: grid;
    grid-template-columns: repeat(6,minmax(100px,1fr));
    gap: .5rem;
    figure {
        margin: 0;
    }
    .advent-link {
        padding: 0;
        text-decoration: none;
        color: currentColor;
        width: 100%;
        height: 100%;
    }
    .mod-articles-advent-item-content {
        aspect-ratio: 1;
        transition: all .2s ease-in-out;
        display: flex;
        justify-content: center;
        align-items: center;
        box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.16);
        &:hover {
            transform: scale(1.025);
        }
    }
    span {
        font-size: 4rem;
        color: #fff;
    }
}
@media (max-width: 768px) {
    .advent-grid {
        grid-template-columns: repeat(3,minmax(80px,1fr));
    }
}

Module

As mentioned above we will use only a few parameters from the module:

  • Mode: Normal
  • Articles to Display: 24
  • Select the category (e.g. Advent)
  • Under Ordering select "Random"
  • Under Advanced select the layout "advent"

Configuration module

Configuration module

Configuration moduleYou can place the module on a position from your template (e.g. top-a in Cassiopeia) or insert it on an article that is linked to a menu item.

The result looks like this:

Screenshot from Advent Calendar

When you click on a "door" you get the content of the corresponding article on a modal box:

Article opened on a modal window

If the link to the article doesn't work, you can change the popupOptions to:

$popupOptions['src'] = 'index.php?option=com_content&view=article&id=' . $item->id . '&catid=' . $item->catid . '&layout=modal&tmpl=component';

Alternatively you can create a menu item for the category. In order to keep the articles secret, you can set the menu item to not be displayed in the menu.

Alternative layout

Another option to create an advent calendar is to have a background image and display the articles as boxes with the day number on it.

The override code looks like this:

advent2.php

<?php

/**
 * @package     Joomla.Site
 * @subpackage  mod_articles
 *
 * @copyright   (C) 2024 Open Source Matters, Inc. <https://www.joomla.org>
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
use Joomla\CMS\Router\Route;

/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $app->getDocument()->getWebAssetManager();
$wa->useScript('joomla.dialog-autocreate');

if (!$list) {
    return;
}

$items = $list;

$today = Factory::getDate()->format('Y-m-d');

// Set up the modal options that will be used for module editor
$popupOptions = [
    'popupType'  => 'iframe',
    'className'  => 'adventskalender',
];

?>

<div class="advent-grid advent-bg">
    <?php foreach ($items as $item) : ?>
        <?php
            // Get the images for this article
            $images  = json_decode($item->images);

            // Get the custom fields for this article
            $jcfields = FieldsHelper::getFields('com_content.article', $item, true);

            // Create an associative array for easier access by field name
            foreach($jcfields as $jcfield) {
                $jcfields[$jcfield->name] = $jcfield;
            }

            // Ensure the field exists and is a valid date
            $openDay = isset($jcfields['day']) ? date('Y-m-d', strtotime($jcfields['day']->value)) : null;

            // Set up popup options
            $popupOptions['src'] = Route::_('index.php?option=com_content&view=article&id=' . $item->id . '&catid=' . $item->catid . '&layout=modal&tmpl=component', false);
            $popupOptions['textHeader'] = $item->title;

            $layoutAttr = [
                'src' => $images->image_intro,
                'alt' => empty($images->image_intro_alt) ? '' : $images->image_intro_alt,
            ];
        ?>
        <div class="mod-articles-advent-item-content">

            <?php if ($openDay <= $today) : ?>
            <button type="button"
                data-joomla-dialog="<?php echo htmlspecialchars(json_encode($popupOptions, JSON_UNESCAPED_SLASHES)) ?>"
                class="btn btn-link advent-link"
                aria-label="<?php echo $item->title; ?>"
                id="title-<?php echo $item->id; ?>"
                data-module-id="<?php echo $item->id; ?>">
                <span><?php echo date('j', strtotime($openDay)); ?></span>
            </button>
            <?php else : ?>
                <span><?php echo date('j', strtotime($openDay)); ?></span>
            <?php endif; ?>

        </div>
    <?php endforeach; ?>
</div>

Instead of the intro image from the article I extracted the day from the field value:

<?php echo date('j', strtotime($openDay)); ?>

Few additional lines of CSS are needed:

.advent-bg {
    padding: .5rem;
    background-image: url(../../../../../images/advent/christmas-background-4621177_1920.jpg);
    background-repeat: no-repeat;
    background-size: cover;
    .mod-articles-advent-item-content {
        box-shadow: 3px 3px 3px rgba(255, 255, 255, 0.5);
        border: 1px solid #d5d5d5;
    }
}

And the result is very nice:

Second variant of the Advent CAlendar
Of course the idea is not limited to advent calendars. You can use it for a promotion event as well, for example to give discounts to products or services during the Black Week. You can modify the code to let the “doors” open only on the assigned day:

<?php if ($openDay == $today) : ?>

 

If I have a thousand ideas and only one turns out to be good, I am satisfied. - Alfred Nobel

In this spirit: test the new Articles module, play with the parameters and get new ideas for your website!

Big thanks to Stefan Wendhausen for checking and improving the code.

The images are from Pixabay.


Spanish translation of this article: https://mejorconjoomla.com/noticias/magazine/como-crear-un-calendario-de-adviento-utilizando-el-nuevo-modulo-de-articulos-en-joomla-5-2 

Italian translation of this article: https://www.joomlaitalia.it/guide-e-tutorial/traduzioni-joomla-magazine/realizzare-un-calendario-dellavvento 

About the author

Since 2008, I am creating websites with Joomla. In 2014 I started volunteering in the Joomla community and I am now active in various teams (Maintainers, Accessibility, Events). I like to write articles for the Joomla Magazine and other blogs. Since 2019, I have been (co-)organising the JoomlaDay Germany / D-A-CH.

Visit website

Some articles published on the Joomla Community Magazine represent the personal opinion or experience of the Author on the specific topic and might not be aligned to the official position of the Joomla Project

Comments