In the last article in the Joomla 4 Templating series we looked at the Web Asset Manager, what it does and how we'd use it for the simple
template.
In this article we'll look at the structure and set up for the main templating file /templates/simple/index.php
index.php
We'll begin by defining what we need to use
. Apart from $app
which gives us many basic utilities from the Factory class, we'll want to use the HTMLHelper
which not only provides us with the Web Asset Manager, but also functions to preload external assets as well as the image helper functions. We'll also use URI
to create clickable links when we get to the body section.
index.php
<?php
defined( '_JEXEC' ) or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Uri\Uri;
$app = Factory::getApplication();
//get sitename for inclusion as alt in logo image
$sitename = htmlspecialchars($app->get('sitename'), ENT_QUOTES, 'UTF-8');
//get Web Asset Manager
$wa = $this->getWebAssetManager();
//preload the external Bootstrap javascript
//this resolves the DNS ahead of time
$this->getPreloadManager()->dnsPrefetch('https://cdn.jsdelivr.net');
//create the link for favicon in /media/site/templates/simple/images
//true means look in the media folder, specifically our template
//1 means return it as a tag ready to go
$this->addHeadLink(HTMLHelper::_('image', 'favicon.png', '', [], true, 1), 'icon', 'rel', ['type' => 'image/png']);
Adding the Google Fonts
In the first article of this Joomla 4 templating series, we added a user parameter with a language string into the template area of the admin backend where a user could paste in the url of the Google Font(s) for the simple
template. We put this into lines 45-51 of the templateDetails.xml file. There are several things we need to do to get these Google Fonts into our template:
- Obtain the url that the user pasted in - the name of the variable in the templateDetails.xml file is
googlefonts
- Preconnect to the Google servers which is recommended to cut down on lookup time. The Preconnect function is sent in the headers and deals with DNS lookup, TLS negotiation and handshake before the fonts are actually downloaded
- Register and use the Google Font(s) with the Web Asset Manager
index.php - continued
//did user paste in google fonts url?
//the name of the language variable is googlefonts
$googlefonts = trim($this->params->get('googlefonts', '', 'string'));
//if it exists:
if($googlefonts !=='') {
$this->getPreloadManager()->preconnect('https://fonts.googleapis.com/', ['crossorigin' => 'anonymous']);
$this->getPreloadManager()->preconnect('https://fonts.gstatic.com/', ['crossorigin' => 'anonymous']);
$wa->registerAndUseStyle('googlefonts', $googlefonts, [], ['crossorigin' => 'anonymous'], []);
}
Assuming the user pasted in the following url: https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@200&family=Roboto:wgth@200,300&display=swap
the tags generated from the code above will result in what Google Fonts recommends which is:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@200&family=Roboto:wgth@200,300&display=swap" rel="stylesheet">
Notice that we didn't register the Google Fonts in our joomla.asset.json
file. The reason for that is because it's a user generated parameter. We can't put into that file what we don't yet know. In order to generate the stylesheet, we simply registerAndUseStyle on the fly with the Web Asset Manager. In that same function, we specified that we wanted the attribute crossorigin
to be anonymous.
Meta tags, Body Class, Logo and Use Styles and Scripts
We finish out this section by adding a Meta tag that's required for Bootstrap. Next we extract any classes added to the menu item for this page and generate an img
tag for the logo (in /media/templates/site/images
). Both of these will be used later on in the body section of the template. Finally, we'll use (activate) our template's stylesheets and scripts with the Web Asset Manager.
index.php - continued
//meta tag required for Bootstrap
$this->setMetaData('viewport', 'width=device-width, initial-scale=1');
//check if a class was added to this menu item
//the class will be applied to the body tag
$menu = $app->getMenu()->getActive();
$pageclass=$menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : '';
//get the img tag for the logo in the body section
//true - search in media folder
//0 - return it as an img tag
//$sitename forms the alt tag
$logo = HTMLHelper::_('image', 'logo.png', $sitename, ['class' => 'bannerlogo img-fluid', 'itemprop' => 'logo'], true, 0);
//USE the scripts/styles in joomla.asset.json
$wa->useStyle('template.style.simple')
->useScript('template.script.simple');
?>
You might be asking: Why have you only used 2 of the assets in joomla.asset.json - there were three, right?
Correct, there were three assets in joomla.asset.json:
- style.css (name: template.style.wm)
- external javascript file from Bootstrap's CDN
- template.js (name: template.script.simple with a dependency on 2.)
However, since template.js (3) has a dependency on the external Bootstrap javascript (2), by calling $wa->useScript('template.script.simple')
it must first call useScript on the Bootstrap external file before it.
It's just a shortcut. All 3 files will get loaded.
Putting it together in the HEAD
Now we'll use all the prep above to construct the HEAD tag of index.php.
index.php - continued
<!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
<head>
<jdoc:include type="metas" />
<jdoc:include type="styles" />
<jdoc:include type="scripts" />
</head>
Neat. $this->setMetaData()
functions get put into the jdoc meta tags. The $wa->(useStyle) / $wa->(useScript)
functions get put into the jdoc styles and scripts.
And yes you can improvise. Have a look at the below. A sneaky javascript has been inserted to appear after all the other scripts are loaded. Bear in mind, it won't be tracked by the Web Asset Manager.
<!DOCTYPE html> <html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>"> <head> <jdoc:include type="metas" /> <jdoc:include type="styles" /> <jdoc:include type="scripts" /> <script src="https://xxxxx.com/sneakyscript.js" defer></script> </head>
BODY
This is a barebones body with no real layout or style, but it covers some of the basics of developer code. After you've installed the template and generated some css from the Bootstrap scss you'll be able to add nice layouts, colors and so on.
Notice the two jdoc
tags? The first one is to display system messages. The second one is needed in order to render the main component for this page. If you're on the Home page, then you'll need to have something (article, category blog etc) referenced from the Home page in the Main Menu. To do that real quick, you can create a test article, then go the Menu-Main Menu, open Home, change the Menu Item type to Single Article, click on Select Article and choose your test article. The test article will now display wherever the jdoc
reference is placed in the template on your home page.
We've also added a search module in position: search
which was defined in the template manifest: templateDetails.xml. Of course for it to show you'll need to go to System-Site Modules and add in a Smart Search Module, using the position: search
.
index.php - continued
<body class="site <?php echo empty($pageclass) ? '': $pageclass; ?>" id="top">
<div class="container">
<header>
<!-- clickable logo -->
<a href="<?php echo Uri::base(); ?>">
<?php echo $logo; ?>
</a>
<h1><?php echo $sitename; ?></h1>
</header>
<main>
<jdoc:include type="message" />
<jdoc:include type="component" />
</main>
<footer>
<!-- search module -->
<?php if ($this->countModules('search', true)) : ?>
<div class="someclass">
<jdoc:include type="modules" name="search" style="none" />
</div>
<?php endif; ?>
<!-- end search module -->
</footer>
</div>
</body>
</html>
Notes
Joomla relies heavily on menus. If you wanted to add a css class to the Home page itself, open up Home in the Main Menu and tab over to Page Display. You can add your class there in Page Class. The $pageclass variable is extracted from here.
Although we created the <img>
tag for the logo using the HTMLHelper
class which relies on the Web Asset Manager to track files in /media/templates/site/simple
, we could have also generated it in the body itself using Uri
, however we would have had to provide a path, as in:
<img src="<?php echo Uri::base(true). '/media/templates/site/simple/images/logo.png'; ?>" alt="put your sitename here">
Uri::base(true)
means provide a relative url, which is fine for images. Without the true it provides a full URL.
What's Next?
In the next article in the Joomla 4 Templating series, we'll code the error template in /templates/simple/error.php