8 minutes reading time (1650 words)

How to create an Advent Calendar using the new Articles Module in Joomla 5.2

November-Advent-Calendar

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 

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

5
Continuing on the Path to a Peak Performing Joomla...
The anatomy of smart search in Joomla 5 Part 2: Cr...
 

Comments 2

Already Registered? Login Here
Nelson Fernando Bautista Pinzon on Wednesday, 27 November 2024 17:25
Good idea using module options directly without overrides.

Kind regards.

The module is interesting, but the idea is not to make the user who has just arrived to Joomla make modifications in templates, php, css and other files, especially if he is a new user.

It is fine for programmers and some users with some knowledge in file manipulation, but for the average user it is not a good idea.

The idea is that the average user uses the module directly and the options can be managed from the options of the module itself without having to mess with codes, templates or overrides.

0
Kind regards. The module is interesting, but the idea is not to make the user who has just arrived to Joomla make modifications in templates, php, css and other files, especially if he is a new user. It is fine for programmers and some users with some knowledge in file manipulation, but for the average user it is not a good idea. The idea is that the average user uses the module directly and the options can be managed from the options of the module itself without having to mess with codes, templates or overrides.
Viviana Menzel on Thursday, 28 November 2024 14:51
Overrides make Joomla more flexible

Thank you for your comment. Since there is no special module for an advent calendar out there, it is good one can use overrides to create such things. That is some special in Joomla and makes it super flexible. The idea of the override tutorials is to show new users, that they can changes things without breaking Joomla and without installing big extensions.

0
Thank you for your comment. Since there is no special module for an advent calendar out there, it is good one can use overrides to create such things. That is some special in Joomla and makes it super flexible. The idea of the override tutorials is to show new users, that they can changes things without breaking Joomla and without installing big extensions.

By accepting you will be accessing a service provided by a third-party external to https://magazine.joomla.org/