Joomla Modules and Positions
|
This content was generated with the assistance of AI and should be verified against the official Joomla documentation before being relied on in production. This sub-section’s Joomla bibliography lists the reference material consulted while preparing these pages. |
A module is the small block of output that Joomla draws around the main component on a page: a menu, a search box, a login form, a list of latest articles, a block of custom HTML. Modules are what turn one component output into a finished page layout, and they are the part of a Joomla site that site builders touch most often after articles and menus. This page explains how a module is selected for a request, how template positions decide where it appears, how the menu assignment, access, language and publishing settings filter it, how a module style wraps it in markup, which module types ship in core, and the module versioning and multilingual associations introduced in Joomla 6.1. It was checked against the official documentation and the 6.2 source tree on 2026-10-30. The behaviour described is that of Joomla 6.2 (current, requiring PHP 8.3 or newer); where Joomla 5.4 (security fixes only) differs, the text says so. Joomla 4.x and 3.x are end of life.
The examples belong to the Tallpine Hiking Club, the fictitious mountain club used across this sub-section. Its site
uses the child template cassiopeia_tallpine (see Child templates) and needs a
main menu, a trail-conditions notice for members, a breadcrumb trail, a language switcher for English and German, a
search box and a banner for partner shops. Writing your own module is covered in
Module development; this page is about using and placing modules.
What a module is, and who works with it
Technically a module is an extension of type module (see
Extension types, manifests and packaging) whose element
name starts with mod_. The extension supplies code and a manifest. An instance of the module, which is what you
create in the Administrator, is a row in the #__modules table holding a title, a position, a few state fields
(published, access, language, publishing dates), the module’s parameters as JSON, and, for the Custom module, its
HTML content. One extension can have many instances, each with its own title, parameters and position.
Several roles work with modules:
-
Editors and site builders create instances in Content → Site Modules, choose a position and a menu assignment, and reorder them.
-
Administrators manage System → Administrator Modules, the modules of the back end (dashboard icons, the user menu, the toolbar), and decide who may edit modules.
-
Themers declare positions in
templateDetails.xml, place them inindex.phpand write module styles. -
Developers write module extensions, and the Dispatcher and Helper pattern is described in Module development.
Site modules and administrator modules
Joomla keeps two sets of modules, selected by the client_id column of the module row. Site modules (client_id 0)
render on the public site, in the positions of the active site template. Administrator modules (client_id 1) render
in the back end, in the positions of the active administrator template, which is Atum by default (see
The Administrator template Atum).
| Aspect | Site modules | Administrator modules |
|---|---|---|
Menu in the Administrator |
Content → Site Modules |
System → Administrator Modules |
Template that declares positions |
The site template, for example Cassiopeia |
The administrator template, by default Atum |
Typical positions |
|
|
Menu assignment tab |
Present, because the site renders per menu item |
Absent |
Associations tab (Joomla 6.1) |
Present when multilingual associations are enabled |
Absent |
Module types |
Menu, Custom, Articles, Breadcrumbs, Login, Smart Search and more |
Custom, Latest Actions, Logged-in Users, Quick Icons, Privacy dashboard and more |
The module edit form in the 6.2 source shows the Menu Assignment tab only for site modules, and the Associations tab only when associations are enabled for a site module. Everything else on this page, positions, styles, access, language and publishing, applies to both sets unless the text says otherwise.
How a module reaches the page
A module appears on a page only when a template asks for its position. The template contains one
<jdoc:include type="modules" name="sidebar-right" style="card" /> element per position. When the document is
rendered, Joomla replaces that element with the output of every module that passes all the filters, in order.
The filtering happens in ModuleHelper::getModuleList() in libraries/src/Helper/ModuleHelper.php. In the 6.2
source a single query joins #__modules with #__modules_menu and #__extensions and keeps the rows where the
module is published, its extension is enabled, its client matches the current application, its access level is one of
the user’s authorised view levels, the current time is inside its publishing window, and the menu assignment matches the
current Itemid. The result is cached in the com_modules cache group under a key built from the user’s view levels,
the client, the menu item and, on a multilingual site, the language tag. The rows are ordered by position and then by
the ordering column. Because that list is cached, a change to a module is normally visible at once (saving a module
clears the group), while a change made directly in the database may need the cache cleared in
System → Clear Cache.
Two consequences matter in daily work:
-
A module whose extension is disabled in System → Manage → Extensions disappears from every position, even though its instance still shows as published.
-
The filters combine with AND. A module set to "On all pages" but with the access level Registered is still hidden from visitors who are not logged in.
Positions
A position is a named slot in a template. It is only a string: nothing is registered in a table, and a module row
simply stores the position name in its position column. Several modules may share one position and are drawn in
their Ordering sequence. A module whose position is empty is not drawn. A module placed in a position that the
active template does not output is not drawn either, which is the usual reason that "the module is published but I
cannot see it" after a template change.
How a template declares positions
A template declares positions in two places that must agree:
-
In
templateDetails.xml, inside<positions>, one<position>element per name. This list feeds the position drop-down in the module editor and the Preview mode. It does not by itself draw anything. -
In the template’s
index.php(orcomponent.php,error.php), onejdoc:includeelement per position. This is what actually draws the modules.
Cassiopeia in the 6.2 source declares eighteen positions: topbar, below-top, menu, search, banner, top-a,
top-b, main-top, main-bottom, breadcrumbs, sidebar-left, sidebar-right, bottom-a, bottom-b, footer,
debug, error-403 and error-404. The last two are used directly by the template’s error.php and are listed
in the manifest only so that they appear in the position list. The User Guide mentions sixteen positions in its
Cassiopeia description; the two error positions account for the difference.
<!-- templates/cassiopeia_tallpine/templateDetails.xml (excerpt) -->
<extension type="template" client="site" method="upgrade">
<name>cassiopeia_tallpine</name>
<version>1.0.0</version>
<inheritable>0</inheritable>
<parent>cassiopeia</parent>
<positions>
<!-- the module editor reads only this manifest, so list the parent's positions here too -->
<position>trail-conditions</position>
<position>partner-strip</position>
</positions>
</extension>
A child template does not inherit the parent’s position list at run time. The module editor reads the positions from the
templateDetails.xml of the active template only, so the child’s manifest must list every position it wants offered,
including the parent’s (the Templates manager copies them there when it creates the child). The Tallpine child adds
trail-conditions and partner-strip to that list. They only show up in the editor’s drop-down once the template’s index.php outputs them, or, for
positions that are not drawn directly, once they are listed in templateDetails.xml. The child-template mechanics,
including how index.php is overridden, are covered in Child templates.
Placing a position in index.php
Cassiopeia wraps each jdoc:include in a countModules test so that an empty position produces no wrapper markup
and, on the layout grid, no empty column. A position is declared and used like this in a custom layout:
<?php
// templates/cassiopeia_tallpine/index.php (excerpt)
defined('_JEXEC') or die;
?>
<?php if ($this->countModules('trail-conditions', true)) : ?>
<aside class="container-trail-conditions" aria-label="Trail conditions">
<jdoc:include type="modules" name="trail-conditions" style="card" />
</aside>
<?php endif; ?>
<main>
<jdoc:include type="modules" name="breadcrumbs" style="none" />
<jdoc:include type="message" />
<jdoc:include type="component" />
</main>
Source: Joomla Manual: Templates
$this->countModules('trail-conditions', true) counts the modules that would render in that position. The second
argument asks for modules that produce non-empty content; a module whose dispatcher outputs
nothing then does not make the wrapper appear. The style attribute names the default module style for every module
in the position (see Module styles (chrome)). A position may also be written in a condition such as
countModules('sidebar-left + sidebar-right') to count several at once.
The jdoc:include type="modules" element accepts name (the position) and style. Other type values include
component, message, metas, styles, scripts and module; the last renders one module by name. For asset
loading in module and template code see Web Asset Manager.
Cassiopeia’s layout
Cassiopeia is a Bootstrap 5 grid. Its positions group into a header area (topbar, below-top, menu, search,
banner), a row above the content (top-a, top-b), a three-column body (sidebar-left, the component with
breadcrumbs, main-top and main-bottom around it, sidebar-right), a row below the content (bottom-a,
bottom-b), the footer, and a debug position for the debug module. The default style differs by position:
topbar, below-top, menu, search, banner, breadcrumbs, footer and debug use style="none", while the
content and sidebar positions use style="card". That is why a Custom module in sidebar-right appears in a bordered
card and the same module in footer appears bare.
The administrator template Atum declares the positions bottom, debug, menu, sidebar, status, title, top
and toolbar, and lists cpanel, icon, login and customtop as positions that components use directly. The
dashboard is built from cpanel and icon modules, which is why moving a Quick Icons module to another administrator
position takes its icons off the Home Dashboard.
Showing every position: Preview Module Positions
To see where a template draws its positions, even the empty ones, enable the preview switch:
-
In the Administrator open System → Site Templates (or Site Template Styles) and click Options in the toolbar.
-
Set Preview Module Positions to Enabled, then Save & Close.
-
Add
?tp=1to the site URL, or&tp=1if the URL already has a query string, for examplehttps://tallpine.example/?tp=1.
The setting is the template_positions_display parameter of the com_templates component, and its default is
Disabled. With the switch on and tp=1 in the request, ModuleHelper::getModules() prepends a dummy module to every
position that has no real module, with the position name as its title and content, and renderModule() adds the
outline style to the style of every module. The result is a page in which each position is outlined and labelled
with its name and the style in use. Positions that exist in templateDetails.xml but are never output by index.php
still do not show.
Two cautions come from how the switch works. Because it is a global option, any visitor can add ?tp=1 and see the
layout of the site while it is enabled, so turn it off on production sites, as the User Guide recommends. And the
outline style wraps real modules too, so a page previewed with tp=1 is not a faithful rendering of the final markup.
Module assignment to menu items
A site module is shown only on the pages whose menu item it is assigned to. The Menu Assignment tab offers four choices:
| Option | Effect |
|---|---|
On all pages |
The module is shown on every page, including pages without a menu item. This is the default for a new module. |
No pages |
The module is saved but never shown. Use it to park a module without unpublishing it. |
Only on the pages selected |
The module is shown only on the checked menu items. |
On all pages except those selected |
The module is shown everywhere, except on the checked menu items. |
The last two options reveal a Menu Selection tree that lists every menu and its items. The Expand the Menu Subtrees button collapses or opens the tree; a menu or a branch can be checked as a whole. Hiding the breadcrumb trail on the home page is a classic use: choose On all pages except those selected, collapse the tree, expand Main Menu and check Home.
Internally the assignment is stored in #__modules_menu, one row per module and menu item. A menuid of 0 means
"all pages", a positive value is a selected menu item, and a negative value is an excluded one (the item’s id with a
minus sign). "No pages" stores no row, so the join in the query matches nothing. cleanModuleList() then drops any
module that has a row whose negated value equals the current Itemid, which is how "all pages except" works.
-- Read-only: which pages show module 42 ("Trail conditions" notice)?
-- Replace #__ with the configured table prefix.
SELECT mm.menuid, m.title
FROM #__modules AS m
LEFT JOIN #__modules_menu AS mm ON mm.moduleid = m.id
WHERE m.id = 42;
Pitfalls of menu assignment:
-
The assignment is by menu item, not by URL or article. Two menu items pointing at the same category are two different pages for module purposes, and the module query uses the
Itemidof the request. A page that no menu item targets shows only the modules assigned to all pages (and the ones using exclusions for other items). -
A menu item created after the module was saved is not in an "Only on the pages selected" list until someone checks it, while "On all pages" and "On all pages except those selected" cover it automatically.
-
On a multilingual site a menu item exists per language. A module assigned only to the English menu items does not appear on the German pages, even with its language set to "All"; assign the German items too, or use "On all pages".
Module fields: title, state, access, language and publishing
The Module tab of every site module has a content column and a sidebar with the settings common to all types. They
are defined once in administrator/components/com_modules/forms/module.xml:
| Field | Meaning |
|---|---|
Title |
Required. Shown as the module heading when Show Title is on, and used as the accessible name of the region when
the module tag is not a |
Show Title |
Show (the default) or Hide. A hidden title is still used for the |
Position |
The position name. The field offers the positions of every installed template, and also accepts a typed value, which is how a position of a template not yet installed can be pre-filled. Position names are stored in lower case, so use lower case in templates too. |
Status |
Published, Unpublished or Trashed. |
Start Publishing and Finish Publishing |
Optional date and time (stored in UTC and shown in the user’s time zone). Outside this window the module is not loaded. Joomla does not unpublish the row at the end of the window; the query simply excludes it. |
Access |
One of the site’s access levels: Public, Guest, Registered, Special or a custom level such as Trail Wardens. Only users whose groups map to that level see the module. |
Ordering |
The sequence inside the position. The list is linked to the position field and shows the other modules of the position. |
Language |
All (stored as |
Note |
A free text of up to 255 characters shown in the list. Use it to record why a module exists. |
Version Note |
Up to 255 characters, stored with a saved version (see Module versioning (Joomla 6.1)). |
Ordering
Open Content → Site Modules, sort the list by the Ordering column (the column heading icon), then drag the handle of a row to move it up or down inside its position. Dragging works within one position at a time. The same ordering applies on every page where the module is shown. Filter the list by position first, otherwise the drag order of unrelated modules is meaningless.
Access
The access level is the visibility gate for visitors, and the Permissions tab is a separate gate for editors.
-
Access decides who sees the module on the site. The check uses the user’s authorised view levels (
getAuthorisedViewLevels()), so a module with level Trail Wardens is shown to members of the custom Trail Warden group and to nobody else. The Tallpine trail-conditions notice for members uses this. -
Permissions decides who may create, edit, change the state of or delete modules. A group needs Create, Edit and Edit State on the Modules component. The tab appears only for users who have Configure ACL & Options (
core.admin). Roles, groups and access levels are explained in Users, groups, access levels and ACL.
A module hidden by its access level is still sent to the caching layer under a key that contains the user’s view levels, so a cached page for visitors does not leak a module meant for members. The corollary is that page caching and the Progressive caching option multiply cache entries on sites with many access levels (see Caching and performance). The access level is a presentation filter, not a security boundary: a Registered module that prints private data to a hidden element still sends that data to anyone who can load the page. Put sensitive content in a component whose own ACL decides.
Language
The Language field has an effect only on a multilingual site, meaning when the Language Filter plugin is enabled (see
Multilingual sites). With the plugin on, getModuleList() keeps modules
whose language is the current language or *. With the plugin off, the field is stored but ignored, so a German
module still shows on an English-only site. In the back end, administrator-module language filtering needs the
corresponding administrator multilingual setting.
For Tallpine, the site has one Main Menu module per language, each set to its language and its own menu, and a single Language Switcher module set to All.
Publishing states and dates
The states are Published, Unpublished and Trashed. Trashed modules are kept until emptied from the Trashed filter. The start and finish dates make time-limited banners easy: the Tallpine "Winter hut booking opens" notice has a start date and a finish date and needs no cleanup afterwards. Pitfalls are the time zone (the dates are converted from the user’s time zone to UTC on save) and caching: the module list is cached, so the change appears when the cache entry expires or is cleared, not at the exact second.
Module styles (chrome)
A module style, historically called chrome, is the wrapper markup around a module’s output. The module itself produces the content; the style adds the heading, the container and the CSS classes. Choosing a style changes the look of a module without touching the module.
Styles are layout files in a chromes folder:
-
the system styles live in
layouts/chromes/(for examplenone.php,html5.php,table.php,outline.php); -
a template can add or replace styles in
templates/<name>/html/layouts/chromes/(Cassiopeia shipscard.phpandnoCard.phpthere).
The style used for a module is chosen in this order, as the 6.2 renderModule() does it: the module’s own
Module Style setting on the Advanced tab, when it is not empty; otherwise the style attribute of the
jdoc:include in the template; otherwise none. When Preview Module Positions is active, outline is appended. A
space-separated list such as style="card outline" applies the layouts in sequence, each wrapping the previous one.
| Style | What it outputs |
|---|---|
|
Only the module content. No wrapper and no heading. |
|
A |
|
Wraps the module in a table; the heading becomes a table header cell. A legacy style kept for old markup. |
|
A labelled box showing the position and style names, used by the position preview. |
|
Cassiopeia style. A Bootstrap card: the module tag carries the classes |
|
Cassiopeia style. Same classes as |
The Advanced tab
The Advanced tab of every module is defined in administrator/components/com_modules/forms/advanced.xml and
carries the fields that control the wrapper:
-
Module Tag: the HTML element,
divby default, orsection,aside,nav,address,article,footer,headerand so on. When the tag is not adiv, the style addsaria-labelledby(title shown) oraria-label(title hidden), which helps screen reader users move between landmarks. -
Bootstrap Size: a value from 0 to 12 for the grid column width, used by templates that read it.
-
Header Tag:
h3by default, fromh1toh6andp. Choose the heading level that fits the page outline. -
Header Class: CSS classes for the heading. The value is validated as CSS identifiers.
-
Module Style: a list of the styles available in the active template and the system, written as
<Template>-<style>, for exampleCassiopeia-noCardorSystem-html5. The value is split at the first dash: the first part names the template whosehtml/layoutsfolder holds the style (Systemmeans the system layouts), the second the style.
Most modules also offer Module Class (moduleclass_sfx) on their own advanced tab. It is appended to the
container’s class attribute, so a module class of text-center centres its content, and a tallpine-notice class can be
styled in user.css or in the child template’s own stylesheet. A leading space in the old suffix convention is no longer
needed in Cassiopeia, but one does no harm.
Writing a style for the child template
The Tallpine child template adds a style that renders members' notices as a Bootstrap alert. A file in
templates/cassiopeia_tallpine/html/layouts/chromes/ is found automatically.
<?php
// templates/cassiopeia_tallpine/html/layouts/chromes/notice.php
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
$module = $displayData['module'];
$params = $displayData['params'];
if ($module->content === null || $module->content === '') {
return;
}
$moduleClass = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_QUOTES, 'UTF-8');
?>
<div class="alert alert-info tallpine-notice <?php echo $moduleClass; ?>" role="note">
<?php if ($module->showtitle) : ?>
<h3 class="alert-heading"><?php echo htmlspecialchars($module->title, ENT_QUOTES, 'UTF-8'); ?></h3>
<?php endif; ?>
<?php echo $module->content; ?>
</div>
Source: Joomla Manual: Web Asset Manager (assets for chromes follow the same registry) and Joomla CMS source: the Cassiopeia card chrome
The file name is the style name, so notice.php becomes a Cassiopeia_tallpine-notice option on the module’s Advanced
tab and style="notice" in index.php. Return early on empty content as the core styles do, escape every value the
chrome prints, and never print $module->content through an extra filter that strips markup the module meant to emit.
More on layouts, overrides and chromes is in
Layouts and module chromes and
Template overrides and alternative layouts.
Place the module in the template with:
<jdoc:include type="modules" name="trail-conditions" style="notice" />
Source: Joomla User Guide: Module Styles
The core module types
Content → Site Modules → New lists the module types installed. The User Guide counts twenty-four types in core:
Articles (Archived, Categories, Category, Latest, Most Read, Newsflash, Related), Banners, Breadcrumbs, Custom, Feed
Display, Footer, Language Switcher, Latest Users, Login, Menu, Random Image, Smart Search, Statistics, Syndication
Feeds, Tags (Popular, Similar), Who’s Online and Wrapper. The 6.2 source tree also contains the newer unified
Articles module (mod_articles, version 5.2.0 in the manifest), which sits beside the older article modules.
The sections below cover the types Tallpine uses most.
Menu (mod_menu)
Draws a menu in a position. Its basic parameters are Select Menu (menutype), Base Item (base), Start Level
(startLevel), End Level (endLevel) and Show Sub-menu Items (showAllChildren). Start and end level slice the tree
so that a module in sidebar-left can show only the children of the current section. The advanced tab adds the menu tag
ID, menu class, layout and caching. The menu items themselves are managed in Menus, see
Menus and menu items. In Cassiopeia the main menu module goes in menu
(style none); the layout draws a Bootstrap navbar, so the choice of position and style matters.
Custom (mod_custom)
A module whose content is HTML written in the editor. The basic fields are Prepare Content (prepare_content), which runs
the content plugins on the text so that tags such as {loadmoduleid 7} and email cloaking work, and Background Image
(backgroundimage). Use it for notices, a footer text, an opening banner or a block of links. Because the content is
stored in the module row, it is part of the version history in 6.1 (see
Module versioning (Joomla 6.1)). The editor filters markup according to the text filters set in Global
Configuration, so a script tag typed by a user without the right filter is removed on save.
Articles (mod_articles and the article modules)
Lists articles from a category selection. The unified module has modes, a count, category filtering, child category
handling, include and exclude lists, layouts (list or columns), display switches for title, author, category, date,
hits, tags and intro text, and filters for featured, archived and unpublished articles. The older modules (Latest,
Most Read, Archived, Newsflash, Categories, Category) remain in the 6.2 tree. Tallpine uses the Articles module in
sidebar-right to list the three most recent trail reports from Trails → Alpine.
Breadcrumbs (mod_breadcrumbs)
Shows the trail from the home page to the current page. Parameters: Show 'You are here' (showHere), Show Home
(showHome), Home text (homeText) and Show Last (showLast). In Cassiopeia it belongs in breadcrumbs. The trail
is built from the menu structure and the component’s pathway, so a component that does not add pathway items yields a
short trail.
Login (mod_login)
Draws the login form with the remember-me option, and for a logged-in user a greeting and a logout button. It supports Login Redirection, Logout Redirection, a pre- and post-login text and the option to display the form with links to registration and password reset. The form posts to the user component, so Multi-Factor Authentication (see Security hardening, MFA and passkeys) and the login plugins apply. A login module should be shown over HTTPS only (see Web server, reverse proxy and HTTPS).
Language Switcher (mod_languages)
Shows links, flags or a drop-down to switch content language, built from the content languages and the associations of the page. It needs the Language Filter plugin, content languages and, to switch to the translation of the same article, associations between items. See Multilingual sites.
Smart Search (mod_finder)
A search box for the Smart Search component. It can show a search button, an autocompleter and an advanced-search link
and target a chosen menu item or search filter. The index it queries is built by the Smart Search indexer, see
Smart Search. A page without a Smart Search menu item still works, because the module
supplies the target Itemid.
Banners (mod_banners)
Shows banners managed by the Banners component, by client, category and tag, with a count, ordering and a header and
footer text. The Tallpine partner strip uses it in partner-strip. The component is described in
Contacts, banners and news feeds.
Tags (mod_tags_popular and mod_tags_similar)
Popular Tags lists the most used tags, with a time frame, a maximum count and optional counts. Similar Tags lists
items that share tags with the current item. Tallpine shows family-friendly and dog-friendly this way. See
Categories and tags.
Other types worth knowing
-
Wrapper embeds an external page in an iframe. Treat it with the usual iframe security precautions (the target must allow framing).
-
Syndication Feeds gives a feed link for the current page; Feed Display reads an external RSS or Atom feed.
-
Random Image shows an image from a folder, with the width and height fields leaving the aspect ratio when empty.
-
Footer, Statistics, Latest Users and Who’s Online are simple information modules.
Loading modules inside articles
Modules normally render in positions, but three tags of the Content - Load Modules plugin insert a module into the text of an article, a Custom module or any content that runs the content plugins. The plugin must be enabled, otherwise the tags are shown as plain text.
| Tag | Effect |
|---|---|
|
Renders every module in the named position at that spot. The style is optional. Position names should be lower case. |
|
Renders the first module of the given type ( |
|
Renders the module with the numeric id. No style argument. |
The Module editor button (the Button - Module plugin) inserts these tags from a dialog. A module used this way usually
has "No pages" as its menu assignment and a position with no template output (a made-up one is fine), so it renders
only where the tag is placed. The module’s access level, publishing dates and language still apply. The plugin’s default
style is none; the plugin options set it.
Pitfalls: a tag inside a Custom module requires Prepare Content on; a module included in itself loops, so never put
{loadmoduleid 42} inside module 42; and the tags are not processed in the API application, so headless clients read the
raw tag. A style given in the tag follows the same rules as the Module Style field.
Module versioning (Joomla 6.1)
Joomla has long kept a version history for articles. Joomla 6.1 extends the same history to modules; the release announcement lists it as "Smarter Modules with Versioning and Multilingual Associations". Each save of a module can store a snapshot in the content history, and a Versions button in the module editor toolbar opens the list, where a version can be previewed, compared, restored or protected from deletion with Keep On/Off.
History is off by default for modules. It is controlled in Content → Site Modules → Options (the com_modules
options), which in the 6.2 source offer Enable Versions (save_history, default No) and Maximum Versions
(history_limit). The edit form also has a Version Note field (version_note, up to 255 characters) so that an
editor can describe a change. The module model implements VersionableModelInterface with VersionableModelTrait, the
same contract the article model uses.
<!-- administrator/components/com_modules/config.xml (excerpt, 6.2) -->
<field name="save_history" type="radio" label="JGLOBAL_SAVE_HISTORY_OPTIONS_LABEL"
layout="joomla.form.field.radio.switcher" default="0">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field name="history_limit" type="number" label="JGLOBAL_HISTORY_LIMIT_OPTIONS_LABEL"
filter="integer" validate="number" min="0" />
What this changes in practice:
-
Before 6.1 a mistaken edit of a Custom module or a menu module parameter had no undo apart from a database backup. With versions on, the Tallpine editors can restore the previous "Trail conditions" notice in one click.
-
The history stores the module’s form data, including the parameters. It is subject to the permissions of the Modules component and to the
Maximum Versionslimit, which prunes the oldest unprotected versions. -
A restore creates a new current state; it does not rewrite history.
-
A site upgraded from 6.0 or 5.4 keeps Enable Versions off until someone turns it on, because the option default is No.
-
On Joomla 5.4 and earlier modules have no version history at all, so a team that relies on it needs 6.1 or newer on every environment that edits modules.
Staged content, for example module wording drafted by an author and published by an editor, is better served by Workflows, which cover articles; module versions record changes but do not add an approval step.
Multilingual associations for modules (Joomla 6.1)
On a multilingual site, articles, categories, menu items and contacts can be associated with their translations so that the Language Switcher sends a visitor to the equivalent page. Joomla 6.1 adds the same association to module instances: a German module can be linked to its English counterpart.
The association appears as an Associations tab in the editor of a site module. In the 6.2 source the tab is shown when
Associations::isEnabled() is true and the module is a site module, and the model uses the association context
com_modules.item and the table #__modules. The prerequisites are the same as for other items:
-
The Language Filter system plugin is enabled, and the site has content languages (English and German for Tallpine).
-
The Language Filter plugin option Item Associations is Yes.
-
The module has a specific language (not All), because an association links items of different languages.
Tallpine example
Module "Winter hut notice" language en-GB position trail-conditions
Module "Winterhuetten-Hinweis" language de-DE position trail-conditions
Association: both modules linked in the Associations tab
Associations help editors see which translation a module has and jump between them, and a site’s own code or template can read the association table through the associations helper. They do not change which module is shown: module selection still uses the module’s own language and its menu assignment, as described above. In particular, an associated pair is not "one module with two translations"; each language still needs its own menu assignment and, for a Menu module, its own menu. The Language Switcher’s page-level links come from the page’s items, not from module associations. The wider setup of languages, language switchers and associations for content is in Multilingual sites, and language strings of a module are explained in Language files and internationalisation.
Caching of modules
Each module can cache its own output. Most core modules offer Caching (use global or no caching) and Cache Time on the
Advanced tab; the cache mode is declared in the module’s XML (static, itemid, safeuri or id). A caching
mode of static stores one entry for every page with the same module parameters, which is right for a footer and wrong
for a module that varies by user or page. The module list query is cached separately, as explained above. Details, the
conservative and progressive page caches and Redis are in
Caching and performance.
Practical walkthrough: the Tallpine trail-conditions notice
-
Open Content → Site Modules → New and choose Custom.
-
Title it "Trail conditions", paste the text, set Position to
trail-conditions, Access to Trail Wardens, and Language to English (en-GB). -
On Menu Assignment choose Only on the pages selected and tick the English Trails branch.
-
On Advanced choose Module Style
Cassiopeia_tallpine-noticeand Module Tagaside. -
Optionally set Start Publishing to the start of the season.
-
Save, then reload the English trails page as a Trail Warden. Reload as a visitor: the module is hidden. Add
?tp=1(with the preview option on) if the position does not show at all. -
Duplicate the module with Save as Copy, switch the copy’s language to German, translate it and assign the German menu items. On 6.1 and newer, link the two in the Associations tab.
Common errors and pitfalls
| Symptom | Likely cause and fix |
|---|---|
The module is published but not visible |
Check in this order: extension enabled, module published and inside its dates, access level, menu assignment,
language, and that the template outputs the position (use |
The module appears in the wrong place after a template change |
The position name is not output by the new template. Move the module to a position that exists. |
Position drop-down lacks a new position |
It is not listed in |
The module is visible on pages where it should be hidden |
Another instance with a different assignment, a cached list, or "On all pages" on a duplicate. Filter the module list by position. |
|
The Content - Load Modules plugin is disabled, or the text is not run through content plugins (a Custom module without Prepare Content). |
|
Preview Module Positions is still Disabled in the template options. |
The language switcher shows no flags or links |
The Language Filter plugin or the content languages are not set; see the multilingual page. |
Module is shown to the wrong visitors |
The access level, not the menu assignment, controls visibility. A Public module is for everyone. |
A module has an empty card |
The module returns empty output but the style still draws the card; use |
Security notes
-
Treat module HTML like article HTML: the Custom module stores whatever the text filter lets through. Keep the filter for authors strict, and give Super Users alone the "No filtering" group.
-
Do not rely on access levels for secrecy; they hide the module from the page for other users but the content still lives in the database and in any cache you share.
-
Give the Create/Edit permissions of modules only to site builders. A user who can edit a Custom module can put a form, an iframe or a link anywhere the template shows that position.
-
Disable Preview Module Positions on production, and keep the
debugposition output behind the debug setting. -
Modules in
sidebarorstatuspositions of the administrator template run with the viewer’s permissions; third-party administrator modules should check ACL before showing data. See Security in extensions.
Version notes
| Version | Change |
|---|---|
4.0 |
Cassiopeia and Atum replace Protostar and Isis, with the position names listed above and the Cassiopeia module styles
|
4.1 |
Child templates (the child manifest lists every position it offers). |
5.0 |
ES5 assets removed; modules register their assets through the Web Asset Manager. |
5.2 |
The unified Articles module ( |
6.0 |
Legacy |
6.1 |
Module versioning and multilingual associations for modules. |
6.2 |
Current stable release. |
The dates and support windows of each release are in Versions, release cycle and support.
Corrections to older books and tutorials
Joomla! 4 Masterclass (2023) describes module positions and the template position preview with Joomla 4 screens, and
older tutorials still talk about positions of Protostar, such as position-7. Those names do not exist in Cassiopeia or
Atum; use the positions listed above. The same book and older tutorials describe child templates as a brand-new
feature (they have been standard since 4.1, and Joomla 6.0 ships cassiopeia_extended). Neither book treats module
versions and module associations because they arrived in 6.1. Pre-4.0 advice such as <jdoc:include type="modules"
name="left" style="xhtml" /> uses the removed xhtml style; use html5, none or the Cassiopeia styles. The
JModuleHelper class name in Developing Extensions for Joomla! 5 (2023) is the legacy alias discussed in
Where older books and tutorials are outdated.
Where a book and the current User Guide disagree, follow the User Guide.
The User Guide’s module styles page mentions an "inherited" module style in one paragraph but does not list it among the
style options; in the 6.2 source an empty Module Style is what inherits the style from the template’s jdoc:include.