Work In Progress

This book is currently work in progress. Some sections are not yet written. Thank you for your understanding!

Component menus

When we are talking about component menus, what comes in mind? Usually it's just the user's ability to create menu items to specific views of your component in the frontend of the site.

Joomla components are much more than that. To begin with, the XML manifest defines the default component menu and its submenu items. As we've already learned, this can be augmented with customisable Dashboards (introduced in Joomla 4.0) to help site integrators tailor the backend experience of their clients as they wish. Ever since Joomla 3.6 it's possible to apply permissions (ACL rules) to backend menu items to modify the submenu items in a way which makes more sense depending on who is logged in.

Moreover, ever since Joomla 3.7, it is possible to have a custom backend menus. This is one more way for site integrators to fully customise the backend experience of their clients, using menu titles which make sense in the business context they are going to be used instead of the much drier, purely functional and very technical language core Joomla and us third party developers use.

All these features are linked to and defined by the components installed on the site, core and third party. Let's see how you can make the magic happen.

The default component menu

The default component menu is what appears in Joomla's main menu (the sidebar) under the Components menu item. You define this menu in your component's XML manifest, under the <administration> section. Joomla has some partial documentation on how that works.

At the very least, every component needs to have the top level item, a <menu> tag directly under the <administration> section. This controls how your component will appear in the Components menu.

If you want a sub-menu under your top level item you need to also add a <submenu> tag at the same level as the <menu> tag. Unlike the menu tag, this one does not have any attributes. However, it can contain one or more <menu> tags, one per sub-menu item.

[Important]Important

If you define a sub-menu then the top level menu item becomes a toggle for the sub-menu and cannot be clicked. For this reason you will have to duplicate the top level link as a sub-menu item.

[Note]Note

It is possible to have third (or more) level sub-menus by nesting <menu> tags. Just because you can doesn't mean you should. Multi-level menus are user-hostile, especially when the available width to display their label is ever shrinking the deeper you go into the menu structure.

If you find yourself even considering a multi-level menu, you're doing something wrong. Try creating a dashboard instead or otherwise group the functionality of your component so it doesn't rely on a byzantine menu structure.

A very simple extension menu would look like this in your XML manifest (as per the Joomla documentation):

<menu>COM_EXAMPLE</menu>
<submenu>
  <!--
  Note that all & must be escaped to &amp; for the file to be valid
  XML and be parsed by the installer
  -->
  <menu link="anoption=avalue&amp;anoption1=avalue1">COM_EXAMPLE_SUBMENU_ANOPTION</menu>
  <menu view="viewname">COM_EXAMPLE_SUBMENU_VIEWNAME</menu>
</submenu>

This does not tell you the whole truth and is actually a partial, confusing and harmful representation of what Joomla can do. Here is a more realistic example:

<menu>
  <params>
    <dashboard>com_example.something</dashboard>
  </params>
  COM_EXAMPLE
</menu>

<submenu>
<!--
Note that all & must be escaped to &amp; for the file to be valid
XML and be parsed by the installer
-->
  <menu view="welcome">COM_EXAMPLE_MENUS_WELCOME</menu>

  <menu link="index.php?option=com_categories&amp;extension=com_example">
    <params>
      <menu-permission>core.manage;com_categories</menu-permission>
      <menu-quicktask>index.php?option=com_categories&amp;task=category.add&amp;extension=com_example</menu-quicktask>
      <menu-quicktask-title>COM_EXAMPLE_MENUS_ADD_CATEGORY</menu-quicktask-title>
      <menu-quicktask-permission>core.create;com_categories</menu-quicktask-permission>
    </params>
    JCATEGORIES
  </menu>

  <menu view="items">
    <params>
      <menu-permission>core.manage;com_example</menu-permission>
      <menu-quicktask>index.php?option=com_example&amp;task=item.add</menu-quicktask>
      <menu-quicktask-title>COM_EXAMPLE_MENUS_ADD_ITEM</menu-quicktask-title>
      <menu-quicktask-permission>core.create;com_example</menu-quicktask-permission>
    </params>
    COM_EXAMPLE_MENUS_ITEMS
  </menu>
</submenu>

Woah! It's pretty substantially different. This is a better example because it shows you all the interesting and insanely powerful things you can do with the humble component menu. Let's take it easy, break it down to individual bits and pieces and it will all become crystal clear, I promise!

An x-ray of the <menu> tag

Every <menu> tag consist of:

  • Zero or more attributes. These determine what kind of link the rendered menu item will produce.

  • A single, but optional ,<params> element with one or more child elements. These are menu parameters which are used to define menu item access (ACL permissions), whether the menu item should display a Dashboard link and whether the menu item should display a quick action button next to it.

  • Text content, e.g. COM_EXAMPLE_MENUS_WELCOME. This is a language string which is used to translate the menu item's title in the user's language.

    [Note]Note

    The language strings for the component menu items' titles are in the backend system language file, i.e. com_example.sys.ini for a com_example component.

    [Warning]Warning

    Do not use <img> or <span> tags in your language strings to display icons. Some major Joomla extension developers should know better than do that, and yet…

    There are the menu_icon and menu_image parameters to do that correctly, if you really need to. Using a tag at the beginning of your language string breaks alphabetical sorting of the Components menu, making it much harder for end users to navigate it. Finally, as we will see further below, using iconography in menus is a bad idea anyway.

The <menu> attributes

Each menu tag can have a combination of the following attributes:

type

Normally not set. You can set it to separator. In this case do not set a link or view attribute; the text content of the menu item will be rendered as a non-linked header in the menu structure.

target

Only applies if you are using the link attribute. Corresponds to the <a> HTML tag's target attribute. Useful if you want to create a menu item linking to an external site and you'd like to open it in a new tab / window; in this case set target="_blank".

link

A link the browser will navigate to. You should ideally only use this to point to pages of components other than yours, e.g. index.php?option=com_categories&extension=com_example to display the categories management interface through Joomla's com_categories core component.

Note that a link pointing to another page in the site's backend is relative to /administrator. Do not put /administrator in front, though; this would break the menu for sites which are installed in subdirectories.

This attribute is mutually exclusive with view. If both are set, link will be applied.

view

The view of the current component you want to link to.

For example, if we are in the XML manifest of the com_example component and you set view="welcome" it's the same as if you had used link="index.php?option=com_example&view=welcome".

This attribute is mutually exclusive with link. If both are set, link will be applied.

ajaxbadge

While you will normally only see that in menu presets used in Dashboards, this is perfectly supported in the component's menu as well.

When set, a badge will appear next to the title. Joomla will perform an AJAX request to the URL provided in the value of this attribute. This URL is supposed to return a JSON document with the following keys:

{
  "success": true,
  "error": "",
  "data": "something"
}

If the success key is true Joomla will take the data key's value, sanitise its HTML (only allowing a subset of tags and attributes you can find in the build/media_source/system/js/core.es6.js file in Joomla's repository) and put that sanitised HTML in the badge.

This is typically used to display the number of items which require attention.

[Warning]Warning

Do not go overboard with this feature! This AJAX request will run on every page of your site's backend, slowing everything down. I have not yet seen a practical use case where this is even remotely acceptable.

Despite what the Joomla documentation wants you to believe, there is neither an alt nor an img attribute; these existed in Joomla 2.5 and earlier. But there are so many more attributes not mentioned in there.

The <menu> parameters

As we mentioned earlier, the <menu> tag can include an optional <params> tag which, in its turn, contains a number of tags. Everything under <params> is parsed as parameters to the menu item. The tag name is the parameter key and its contents is the parameter's value.

Here are the supported tag names I've discovered by reverse-engineering the code of the backend mod_menu module:

dashboard

If set, it creates a dashboard icon next to the menu item's title, linking to the named dashboard.

Example: <dashboard>com_example.example</dashboard>.

menu-permission

The Joomla ACL permission the user needs to have to see this menu item (and all its sub-items, if any).

To use global permissions (set in the Permissions tab of Global Configuration) use the format <menu-permission>core.manage</menu-permission>

To use component-level permissions (set in the Permissions tab of a component) use the format <menu-permission>core.manage;com_example</menu-permission>

You can NOT ask Joomla to combine multiple permissions i.e. you cannot ask it to only display a menu item if two or more permissions are simultaneously granted; or if one of several permissions is granted. The reason for that can be found in the code of \Joomla\Module\Submenu\Administrator\Menu\Menu::preprocess.

menu-quicktask

Menu items can have an optional “quick task” shown next to them. This is a small button with an icon and no visible text (the text is only made available to users of assistive technologies for accessibility reasons). The value of this parameter is the URL to visit when the quick task button is used. It follows the same rules as the link attribute.

Example: <menu-quicktask>index.php?option=com_example&amp;task=item.add</menu-quicktask>

[Note]Note

While this is typically used to render a [+] icon button to add new items, this is not necessary. You can use whatever action feels right in context and whichever icon you think is appropriate for the action.

menu-quicktask-icon

The icon class for the quick task. If it's not specified it will default to plus.

The contents of this parameter are prefixed with the string literal icon- to create the HTML class attribute. For example, <menu-quicktask-icon>cog</menu-quicktask-icon> will result in class="icon-cog" which displays a cog wheel icon.

menu-quicktask-title

A language string which describes the quick task to users of assistive technologies (e.g. screen readers, Braille displays, …). If not defined, the language string MOD_MENU_QUICKTASK_NEW (New Item) will be used.

menu-quicktask-permission

Equivalent to menu-permission but applies to the quick task instead. Use this to limit who should be able to view the quick task icon.

menu_image

The (relative) URL to an image file to use for the menu item.

This is mutually exclusive with the menu-icon parameter.

[Note]Note

It is generally bad form using images for menu items.

Images, especially raster (bitmap) images, may not display very well and make the backend of the site look cheap and unprofessional.

Images, unlike language strings, are untranslatable and cannot be replaced for different languages and cultures. Iconography with vector images may have radically different meanings depending on the cultural context and personal circumstances. For example, an open palm facing the user with fingers spread out means "stop" in the USA but is a vulgar gesture in Greece and Cyprus (it literally means “I spread feces on your face”). A beer mug is a relatively inoffensive icon unless you're putting that in front of Muslims who are required to abstain from alcohol per their religion or recovering alcoholics (or those who've lost a loved one to a DUI fatal accident) who may find that iconography triggering.

You MUST NOT use an icon instead of human-readable text content for the title of the menu item. This is inaccessible to people with disabilities such as hard-of-seeing or blind people, people with cognitive disabilities etc.

menu_icon

When provided it will set the menu item's icon class to the string literal class- followed by the contents of this parameter. For example, <menu-image>cog<menu-image> will result in class="icon-cog" being applied to the menu item's icon <span> tag.

This is mutually exclusive with the menu_image parameter.

text_separator

Only applies when the type="separator" attribute is used. When set to 1 it will render the separator as an <hr> tag instead of text.