Adding Custom Options to your Joomla Template

In this guide, you will learn how to add custom fields/options to the Joomla template you designed. This guide assumes you already know the basics of Joomla template development. PHP and XML experience is helpful, but not required. I will explain all PHP code used, at a basic level.

To begin, I assume you’ve already created a Joomla template that’s mostly complete. To demonstrate, I’m will modify the “Very Simple Template” that I made in the template development guide. I’m going to add a three options to the template’s config settings. If you’d like to follow along with my examples, you can download and install that template.

file icon Very Simple Template

File name: very_simple_template (2024_01_02 01_51_36 UTC).zip

Author: Kevin Olson

License: MIT

A very simple barebones template you can use for testing or demo purposes

Download: very_simple_template (2024_01_02 01_51_36 UTC).zip

These are the options I’m going for.

  • Container Width: If fixed, it uses a boxy container on desktop. If fluid, the container takes up the full-width of the page.
  • Short Slogan: A short line of text that goes under the website name at the top of the page
  • Theme: The user can select from multiple different CSS files for the template. Each CSS style will have different colors.
The Style Settings We’ll Create

Defining The Fields

To define fields in the options of a template, you must modify the templateDetails.xml file in your template’s folder.

Towards the bottom of the XML document, there’s a <config> section. This is where we can define our fields. If you started with my joomstarter template, there should already be one example field here. If you’ve made a template from scratch, you can easily add a config section.

Add the following code to your templateDetails.xml file, at the end, but before the last </extension> tag.

If you already have a config section, either delete the fields or only keep the ones you plan on using.

templateDetails.xml

<config>
	<fields name="params">
		<fieldset name="advanced">
			<field> </field>
		</fieldset>
	</fields>
</config>Code language: HTML, XML (xml)

Each field is defined in a <field> element. There are many field types to choose from. For this guide, I’m going to be using a boolean/radio field for fluid/fixed with, a text field for the slogan, and a filelist field for the css option.

For a full list of fields and their options, you can see the official Joomla docs on standard field types.

The Radio Field (Container Layout)

To define the container layout as being fixed or fluid, I’m going to use a radio field. Radio fields may be one of two options. Here, it’s going to be a radio field with the label saying “Container Width” and options of either “Fluid” or “Fixed”

This is what it looks like when added:

<config>
		<fields name="params">
			<fieldset name="advanced">
				<field
					name="containerlayout"
					type="radio"
					label="TPL_VERYSIMPLE_CONTAINERLAYOUT"
					default="0"
					layout="joomla.form.field.radio.switcher"
					filter="boolean"
					>
					<option value="0">TPL_VERYSIMPLE_LAYOUTFIXED</option>
					<option value="1">TPL_VERYSIMPLE_LAYOUTFLUID</option>
				</field>
			</fieldset>
		</fields>
	</config>Code language: HTML, XML (xml)

You must define several pieces of information to create a field. For radio buttons, define the name, what type of field it is (radio), the field’s label shown to the user, the default value, the layout, a filter, and the options. The format is shown above.

The name should be a short name used internally with no spaces.

The values in this case will be either 0 if the user wants a fixed layout and 1 if the user wants a fluid layout. We will read these values later in the template using PHP and make a decision based upon it.

The text in caps comes from the language files. Specifically, for my template, it’s coming from site_root/language/en-GB/tpl_verysimple.ini

You could just type the fields and their options in plain text here, if you want. But your template won’t be as easily translatable if someone wants to modify it to work in other languages. The general recommendation is to use the language files for all text being displayed.

I have modified my tpl_verysimple.ini language file to contain the following:

TPL_VERYSIMPLE_CONTAINERLAYOUT="Container Width"
TPL_VERYSIMPLE_LAYOUTFIXED="Fixed"
TPL_VERYSIMPLE_LAYOUTFLUID="Fluid"
TPL_VERYSIMPLE_SLOGAN="Short Slogan"
TPL_VERYSIMPLE_STYLE="Theme"
TPL_VERYSIMPLE_STYLE_DESC="The stylesheet to load with this template"Code language: plaintext (plaintext)

The Text Field (Slogan)

Text fields are a little simpler than radio fields. They just allow users to enter a string of text. Filters can be applied to these text fields if needed, read the official Joomla docs for more information on that. I’m not going to filter this text field.

<field
	name="slogan"
	type="text"
	label="TPL_VERYSIMPLE_SLOGAN"
	default=""
	>
</field>Code language: HTML, XML (xml)

I set the field name to “slogan” it’s of type “text” and the label comes from the language file. The default value is nothing. That’s all I need to create a text field.

The File List Field (Theme/Style)

The last field I want to create allows the user to select from any CSS file in the template’s media folder. My plan is to create multiple stylesheets with slight variations in colors. This way, template users have more options to customize their template if they don’t like the default colors.

The filelist field looks like this:

<field
	name="style"
	type="filelist"
	label="TPL_VERYSIMPLE_STYLE"
	directory="media/templates/site/verysimple/css"
	default="template.min.css"
	description="TPL_VERYSIMPLE_STYLE_DESC"
	fileFilter="css"
	exclude="map"
	hide_none="true"
	>
</field>Code language: HTML, XML (xml)

The name I gave it is “style.” It’s of type filelist. The label again comes from the language file. The directory is where it will source the files from. It’s relative to the Joomla site root directory. Remember to use the media directory for YOUR template. If it’s called something other than “verysimple” you will need to insert your own template alias here.

The default file is my template.min.css file. The description comes from the language file, and is displayed under the selection.

The fileFilter is a regex expression to filter files. I only want “css” files to show here, so I’m filtering for files with “css” in them. My template also has a css.map file in the same css directory. This map file came from Sass when the stylesheet was generated, and is used for development purposes. I don’t want this to be an option, so I’ve excluded files with “map” in them from the selection. Alternatively, I could just delete the map file.

The hide_none=”true” option means the user must select an option. They can’t opt to have no stylesheet. A stylesheet is required.

Now that I’ve configured all my options, my entire file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<extension type="template" client="site" method="upgrade">
	<name>verysimple</name>
	<version>1.10</version>
	<creationDate>Feb 2022</creationDate>
	<author>Your Name</author>
	<authorEmail>Your Email</authorEmail>
	<copyright>(C) 2021</copyright>
	<description>TPL_VERYSIMPLE_XML_DESCRIPTION</description>
	<inheritable>1</inheritable>
	<files>
		<filename>index.php</filename>
		<filename>joomla.asset.json</filename>
		<filename>templateDetails.xml</filename>
		<folder>html</folder>
		<folder>language</folder>
	</files>
	<media destination="templates/site/verysimple" folder="media">
		<folder>js</folder>
		<folder>css</folder>
		<folder>scss</folder>
		<folder>images</folder>
	</media>
	<positions>
		<position>header</position>
		<position>footer</position>
		<position>sidebar</position>
		<position>search</position>
		<position>breadcrumbs</position>
		<position>menu</position>
		<position>content-top</position>
	</positions>
	<languages folder="language">
		<language tag="en-GB">en-GB/tpl_verysimple.ini</language>
		<language tag="en-GB">en-GB/tpl_verysimple.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="advanced">
				<field
					name="containerlayout"
					type="radio"
					label="TPL_VERYSIMPLE_CONTAINERLAYOUT"
					default="0"
					layout="joomla.form.field.radio.switcher"
					filter="boolean"
					>
					<option value="0">TPL_VERYSIMPLE_LAYOUTFIXED</option>
					<option value="1">TPL_VERYSIMPLE_LAYOUTFLUID</option>
				</field>
				<field
					name="slogan"
					type="text"
					label="TPL_VERYSIMPLE_SLOGAN"
					default=""
					>
					</field>

				<field
					name="style"
					type="filelist"
					label="TPL_VERYSIMPLE_STYLE"
					directory="media/templates/site/verysimple/css"
					default="template.min.css"
					description="TPL_VERYSIMPLE_STYLE_DESC"
					fileFilter="css"
					exclude="map"
					hide_none="true"
					>
					</field>
			</fieldset>
		</fields>
	</config>
</extension>Code language: HTML, XML (xml)

After modifying your templateDetails.xml and language files, save them and open the template in the Joomla’s style manager. You should see the fields under the advanced tab. Now that the fields exist, we need to make them do something.

Using The Config Settings

With the fields setup, we can now use the values defined in the template style options to customize the output of our template. To do this, I will edit the template’s index.php file.

The Container Setting

The first setting is for the container. We need to read the config value for the “containerlayout” field. If it’s 0, we use a fixed layout. If it’s 1, we use a fluid layout.

My Very Simple Template is using Bootstrap 5. It already has a fixed/boxy container set up by default. The container class I placed all my other page elements within created this boxy container.

<div class="container">Code language: PHP (php)

To make my container fluid, I can use the bootstrap container-fluid class instead of the container class. So I just need to check what option the user selected and then insert the right class name.

The containerlayout field has potential values of 0 or 1. 0 is fixed, 1 is fluid. If you started with my j4starter template or followed along with my guide on template design, there’s already an example parameter getter line near the top of the index.php file on line 39. This is how we can get information from the config settings.index.php line 39

$testparam =  $this->params->get('testparam');Code language: PHP (php)

I’m going to replace this line with:

$containerlayout =  $this->params->get('containerlayout');Code language: PHP (php)

If you’re not familiar with PHP or programming, a semicolon indicates the end of a statement. Basically, we use them after every line where we instruct the computer to do something.

Now, the php variable $containerlayout will either be 1 or 0 based on what option the user selected.

If $containerlayout is 1, we need to use the “container-fluid” class, if it’s 0, we use the “container” class. So after I get the variable value, I’m going to check what number they entered, and set another variable called $containerclass equal to whichever class should be used.

This uses a php if/else statement.

$containerlayout =  $this->params->get('containerlayout');
if($containerlayout==1){
    $containerclass = 'container-fluid';
}
else{
    $containerclass = 'container';
}Code language: PHP (php)

If $containerlayout equals 1, it sets $containerclass to ‘container-fluid’, if not (else) it sets $containerclass to ‘container’

Now I just need to add the variable into my template’s HTML.

I will replace this section of HTML

<body class="site">

    <div class="container">Code language: PHP (php)

With this:

<body class="site">

    <div class="<?php echo $containerclass ?>">Code language: PHP (php)

The <?php echo $containerclass ?> inserts the class from my $containerclass variable set in the earlier code.

A semicolon here is optional. <?php echo $containerclass ?> and <?php echo $containerclass; ?> will both work. The semicolon is optional if the statement is the last line before a php closing tag ?>

Now, when I load my template, the class used for the container will be set based on the value of the config setting.

The Slogan Setting

The next item to work on is the slogan. If there’s nothing in the slogan text, I won’t display a slogan at all. If something is there, I will display the slogan centered under the title.

I can get the value of the slogan text the same way I got the value for the container layout.

//get the slogan
$slogan =  $this->params->get('slogan');Code language: PHP (php)

I decided to put that line directly after the code where I checked the value of the container layout in the previous example. This way, all the PHP for the options is in the same general area of my file.

Now I have to add the slogan to my template, if it exists.

I’m going to be working with the area directly after <span id="site-title"><?php echo $sitename ?></span> in my simple template example project. Before the row containing the menu.

Here’s what my php/html code looks like after the title:

<span id="site-title"><?php echo $sitename ?></span>

 <?php if($slogan) : ?>
     <span id="slogan"><?php echo $slogan ?></span>
     <?php endif; ?>Code language: HTML, XML (xml)

The line <?php if($slogan) : ?> checks if a slogan exists. It’s functionally equivalent to <?php if($slogan=='') : ?>

The colon : means if that condition is true, print out all the HTML starting from here. So if there’s a slogan, print out the following lines of HTML.

The following line of HTML is for a span with the slogan echoed.

The final line, <?php endif; ?> indicates that this is the end of the php if block of code. The program continues running from this point, regardless of if slogan existed or not.

I’ve taken the liberty of adding some basic CSS styling to the #slogan span.

#slogan{
    text-align: center;
    width: 100%;
    display: block;
}Code language: CSS (css)

This is what it looks like when I set the slogan. If I remove the text from the slogan field, the slogan, and its entire span element, disappear from the page.

The Stylesheet Setting

The last setting we need to configure is loading the selected stylesheet.

Currently, my template loads the css file defined in the joomla.asset.json file. I no longer want it to do this, since the user might select one of multiple CSS files.

The easiest way to do this is to delete the line:

$wa->useStyle('template.verysimple.mainstyles');Code language: PHP (php)

This is the line that was used to get template.min.css from joomla.asset.json in my Very Simple template. Your template may be setup differently.

I’m going to replace that line with this:

$stylesheet =  $this->params->get('style');
$wa->registerAndUseStyle('template.verysimple','media/templates/site/verysimple/css/'.$stylesheet);Code language: PHP (php)

This uses the web asset manager $wa and adds the stylesheet to the page from the media directory. Now, I’ve created two stylesheets – my old template.min.css file and a new template-blue.min.css file. I can swap back and forth between the two in my template style options.

I also realized that FontAwesome, an icon library used in many Joomla extensions, was dependent on the .mainstyles defined in the joomla.asset.json file.

To re-enable FontAwesome, I added this line to index.php after I loaded my template css file. You may, or may not have to do this depending on how your template loads FontAwesome. 

$wa->useStyle('fontawesome');Code language: PHP (php)

Here’s what it looks like when I’m done!

Access Values From Template Layout Files (and other areas)

If you want to access the value of a field from outside your template’s main file, such as in a layout file, you may find that $this->params->get('fieldname'); does not work. This is because you’re outside the template and $this no longer refers to the template object.

First make sure you have a use statement at the top of the file to load Joomla’s Factory class.

use Joomla\CMS\Factory;Code language: PHP (php)

Instead, we can get the value of a field by instantiating a new template object and getting the params from there.

//get the 'test_field' param from templateDetails.xml
$template = Factory::getApplication()->getTemplate(true);
$params = $template->params;
$testField = $params->get('test_field');

if ($testField == 1){
    echo 'test field is 1';
}Code language: PHP (php)

Now you can do whatever you want with the testField value. Of course, you’ll need to change it accordingly to match the name of the field defined in your templateDetails.xml file, and implement your feature accordingly.

Conclusion

This concludes this guide. I’d encourage you to look at the Joomla docs on fields if you need more information about setting up different types of fields. There are many options. Hopefully this guide helped you.

Advanced Ideas:

  • Add an option allowing your users to upload their own favicon from the options page
  • Let admins set the width columns take up in the sidebar and the main content area
  • Let admins define the supported breakpoints for the site grid
  • Add additional styling options based on the above example
  • Let admins pick if fontawesome is loaded locally, not at all, or from a CDN
  • Let admins select multiple font settings, add additional fonts using Google fonts or similar services

If you ran into any issues, download the completed project (below) and compare your files to mine. Feel free to leave comments at the bottom of this page.

Further Resources:

0 0 votes
Article Rating
Subscribe
Notify of
guest
8 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments