Icons have a significant visual effect to have on your website. Did you know that using an icon as a Custom Field is possible? - Creating an override for the Field layout is done in minutes.
Since Font Awesome is included in Joomla's Cassiopeia template, we will use a template override for the Field layout.
Creating overrides in Joomla 4 is relatively easy. It is easier if you can read code and know HTML. Just follow these steps:
Select the "Site Template" to go into the area for creating overrides of Joomla 4.
Select "System" from the left menu.
The difference between Site Templates and Site Template Styles is that the overrides for the Template that is put on the Site Templates place, here you put all your customization of the site. The Styles are set in the separate Site Template Styles, which you only use to change the site's primary colors and add a custom logo and the template's name.
This opens the place where you create the overrides. There is a selection called "Create Overrides"; go into it.
The override we are looking for is a "Layout"-override, and the field, this is located under Layouts ⇒ com_fields, select "Field".
Now go into the editor under HTML ⇒ layouts ⇒ com_fields ⇒ field ⇒ render.php.
REMEMBER TO RENAME THE render.php FILE!
<?php
/**
* @package Joomla.Site
* @subpackage com_fields
*
* @copyright (C) 2016 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\Language\Text;
if (!array_key_exists('field', $displayData)) {
return;
}
$field = $displayData['field'];
$label = Text::_($field->label);
$value = $field->value;
$showLabel = $field->params->get('showlabel');
$prefix = Text::plural($field->params->get('prefix'), $value);
$suffix = Text::plural($field->params->get('suffix'), $value);
$labelClass = $field->params->get('label_render_class');
$valueClass = $field->params->get('value_render_class');
if ($value == '') {
return;
}
?>
<?php if ($showLabel == 1) : ?>
<span class="field-label <?php echo $labelClass; ?>"><?php echo htmlentities($label, ENT_QUOTES | ENT_IGNORE, 'UTF-8'); ?>: </span>
<?php endif; ?>
<?php if ($prefix) : ?>
<span class="field-prefix"><?php echo htmlentities($prefix, ENT_QUOTES | ENT_IGNORE, 'UTF-8'); ?></span>
<?php endif; ?>
<span class="field-value <?php echo $valueClass; ?>"><?php echo $value; ?></span>
<?php if ($suffix) : ?>
<span class="field-suffix"><?php echo htmlentities($suffix, ENT_QUOTES | ENT_IGNORE, 'UTF-8'); ?></span>
<?php endif; ?>
<?php
/**
* @package Joomla.Site
* @subpackage com_fields
*
* @copyright (C) 2016 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\Language\Text;
if (!array_key_exists('field', $displayData)) {
return;
}
$field = $displayData['field'];
$label = Text::_($field->label);
$value = $field->value;
$showLabel = $field->params->get('showlabel');
$prefix = Text::plural($field->params->get('prefix'), $value);
$suffix = Text::plural($field->params->get('suffix'), $value);
$labelClass = $field->params->get('label_render_class');
$valueClass = $field->params->get('value_render_class');
if ($value == '') {
return;
}
?>
<?php if ($showLabel == 1) : ?>
<span class="field-label <?php echo $labelClass; ?>"><?php echo htmlentities($label, ENT_QUOTES | ENT_IGNORE, 'UTF-8'); ?>: </span>
<?php endif; ?>
<?php if ($prefix) : ?>
<span class="field-prefix"><?php echo htmlentities($prefix, ENT_QUOTES | ENT_IGNORE, 'UTF-8'); ?></span>
<?php endif; ?>
<span class="field-value <?php echo $valueClass; ?>"><i class="fa fa-<?php echo $value; ?>"></i></span>
<?php if ($suffix) : ?>
<span class="field-suffix"><?php echo htmlentities($suffix, ENT_QUOTES | ENT_IGNORE, 'UTF-8'); ?></span>
<?php endif; ?>
The best field to use is the "radio-button" field. On the options tab - Go to layouts, and select the desired override.
- LET ME KNOW IF YOU KNOW ANY OTHER WAYS TO DO THIS IN THE COMMENTS BELOW -
The Failed Login Attempts plugin gives you an overview of your failed logins, but you can make it even better by applying a simple override. The override provides a link to more information about who has tried to log in, and you can therefore use other extensions to block the user or take measures.
With the Failed Login Attempts extension installed, you can easily track failed logins on your site, but you can go even further by doing an override to the "default.php" file in your admin template. You can see where the origin of the IP address is coming from by clicking the link. The only downside is that you, on extension updates, get a warning to check the override.
But if you update the override, the warning disappears.
Select "System" from the left menu.
The difference between Administrator Templates and Administrator Template Styles is that the overrides for the Template that is put on the Administrator Templates place, here you put all your customization of the site. The Styles are set in the separate Administrator Template Styles, which you only use to change the site's primary colors and put things like a custom logo and the template's name.
Select the "Administrator Template" to go into the area for creating overrides of Joomla 4.
Now you will go into the place where you create overrides.
<?php
/* ======================================================
# Failed Login Attempts for Joomla! - v2.5.2 (pro version)
# -------------------------------------------------------
# For Joomla! CMS (v4.x)
# Author: Web357 (Yiannis Christodoulou)
# Copyright (©) 2014-2022 Web357. All rights reserved.
# License: GNU/GPLv3, http://www.gnu.org/licenses/gpl-3.0.html
# Website: https:/www.web357.com
# Demo: https://www.web357.com/product/failed-login-attempts-joomla-plugin
# Support:
# Last modified: Tuesday 15 November 2022, 11:04:17 PM
========================================================= */
// No direct access
defined('_JEXEC') or die;
use \Joomla\CMS\HTML\HTMLHelper;
use \Joomla\CMS\Factory;
use \Joomla\CMS\Uri\Uri;
use \Joomla\CMS\Router\Route;
use \Joomla\CMS\Layout\LayoutHelper;
use \Joomla\CMS\Language\Text;
HTMLHelper::addIncludePath(JPATH_COMPONENT . '/helpers/');
HTMLHelper::_('bootstrap.tooltip');
HTMLHelper::_('behavior.multiselect');
if (version_compare(JVERSION, '4.0', 'lt')) {
JHtml::_('formbehavior.chosen', 'select');
}
// Import CSS
$document = Factory::getDocument();
$document->addStyleSheet(JURI::root() . 'administrator/components/com_failedloginattempts/assets/css/failedloginattempts.css');
$user = Factory::getUser();
$userId = $user->get('id');
$listOrder = $this->state->get('list.ordering');
$listDirn = $this->state->get('list.direction');
$sortFields = $this->getSortFields();
?>
<script type="text/javascript">
Joomla.submitbutton = function(task)
{
if (task == 'failedloginattempts.deleteAllLogs')
{
var confirmTask = confirm("<?php echo JText::_('COM_FAILEDLOGINATTEMPTS_DELETE_ALL_CONFIRM_ALERT_MSG'); ?>")
if (confirmTask)
{
Joomla.submitform(task);
}
else
{
return false;
}
}
else
{
Joomla.submitform(task);
}
}
</script>
<form action="<?php echo Route::_('index.php?option=com_failedloginattempts&view=failedloginattempts'); ?>" method="post" name="adminForm" id="adminForm">
<?php if (!empty($this->sidebar)): ?>
<div id="j-sidebar-container" class="span2">
<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="span10">
<?php else : ?>
<div id="j-main-container">
<?php endif; ?>
<?php echo LayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?>
<div class="clearfix"></div>
<table class="table table-striped" id="failedloginattemptList">
<thead>
<tr>
<th width="1%">
<input type="checkbox" name="checkall-toggle" value=""
title="<?php echo Text::_('JGLOBAL_CHECK_ALL'); ?>" onclick="Joomla.checkAll(this)" />
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'JGLOBAL_FIELD_ID_LABEL', 'a.`id`', $listDirn, $listOrder); ?>
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'COM_FAILEDLOGINATTEMPTS_FAILEDLOGINATTEMPTS_IP_ADDRESS', 'a.`ip_address`', $listDirn, $listOrder); ?>
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'COM_FAILEDLOGINATTEMPTS_FAILEDLOGINATTEMPTS_NAME', 'a.`name`', $listDirn, $listOrder); ?>
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'COM_FAILEDLOGINATTEMPTS_FAILEDLOGINATTEMPTS_USERNAME', 'a.`username`', $listDirn, $listOrder); ?>
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'COM_FAILEDLOGINATTEMPTS_FAILEDLOGINATTEMPTS_PASSWORD', 'a.`password`', $listDirn, $listOrder); ?>
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'COM_FAILEDLOGINATTEMPTS_FAILEDLOGINATTEMPTS_STATUS', 'a.`status`', $listDirn, $listOrder); ?>
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'COM_FAILEDLOGINATTEMPTS_FAILEDLOGINATTEMPTS_DATETIME', 'a.`datetime`', $listDirn, $listOrder); ?>
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'COM_FAILEDLOGINATTEMPTS_FAILEDLOGINATTEMPTS_COUNTRY', 'a.`country`', $listDirn, $listOrder); ?>
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'COM_FAILEDLOGINATTEMPTS_FAILEDLOGINATTEMPTS_BROWSER', 'a.`browser`', $listDirn, $listOrder); ?>
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'COM_FAILEDLOGINATTEMPTS_FAILEDLOGINATTEMPTS_OPERATING_SYSTEM', 'a.`operating_system`', $listDirn, $listOrder); ?>
</th>
<th class='left'>
<?php echo JHtml::_('searchtools.sort', 'COM_FAILEDLOGINATTEMPTS_FAILEDLOGINATTEMPTS_WHERE', 'a.`where`', $listDirn, $listOrder); ?>
</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="13">
<?php echo $this->pagination->getListFooter(); ?>
</td>
</tr>
</tfoot>
<tbody>
<?php foreach ($this->items as $i => $item) : ?>
<tr class="row<?php echo $i % 2; ?>">
<td>
<?php echo HTMLHelper::_('grid.id', $i, $item->id); ?>
</td>
<td>
<?php echo $this->escape($item->id); ?>
</td>
<td>
<?php echo $this->escape($item->ip_address); ?>
<a href="https://ip-lookup.net/index.php?ip=<?php echo $this->escape($item->ip_address); ?>" target="_blank"><?php echo $this->escape($item->ip_address); ?></a>
</td>
<td>
<?php echo $this->escape($item->name); ?>
</td>
<td>
<?php echo $this->escape($item->username); ?>
</td>
<td>
<?php
echo $this->escape($item->password);
?>
</td>
<td>
<?php if ($item->status == 'PLG_FLA_SUCCESSFULLY_LOGIN'): ?>
<p class="text-success">
<?php echo Text::_($item->status); ?>
</p>
<?php else: ?>
<p class="text-danger <?php echo (version_compare(JVERSION, '4.0', 'lt') ? 'text-error' : ''); ?>">
<?php echo Text::_($item->status); ?>
</p>
<?php endif; ?>
</td>
<td>
<?php echo $item->datetime; ?>
</td>
<td>
<?php
echo $item->country;
?>
</td>
<td>
<?php
echo $item->browser;
?>
</td>
<td>
<?php
echo $item->operating_system;
?>
</td>
<td>
<?php if ($item->where == 'backend'): ?>
<span class="label label-important badge bg-danger text-white">
<?php echo $item->where; ?>
</span>
<?php else: ?>
<span class="label label-info badge bg-warning text-white">
<?php echo $item->where; ?>
</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<input type="hidden" name="task" value="" />
<input type="hidden" name="boxchecked" value="0" />
<input type="hidden" name="list[fullorder]" value="<?php echo $listOrder; ?> <?php echo $listDirn; ?>" />
<?php echo HTMLHelper::_('form.token'); ?>
<?php echo Web357Framework\Functions::showFooter("com_failedloginattempts", JText::_('COM_FAILEDLOGINATTEMPTS_CLEAN')); ?>
</div>
</form>
<script>
window.toggleField = function (id, task, field) {
var f = document.adminForm,
i = 0,
cbx, cb = f[id];
if (!cb) return false;
while (true) {
cbx = f['cb' + i];
if (!cbx) break;
cbx.checked = false;
i++;
}
var inputField = document.createElement('input');
inputField.type = 'hidden';
inputField.name = 'field';
inputField.value = field;
f.appendChild(inputField);
cb.checked = true;
f.boxchecked.value = 1;
Joomla.submitform(task);
return false;
};
</script>
<a href="https://ip-lookup.net/index.php?ip=<?php echo $this->escape($item->ip_address); ?>" target="_blank"><?php echo $this->escape($item->ip_address); ?></a>
- LET ME KNOW IF YOU KNOW ANY OTHER WAYS TO DO THIS IN THE COMMENTS BELOW -
In Joomla 4, we were introduced to “subforms”, which are great for creating more user-friendly fields for your articles or page, containing the fields in the subform.
The problem is that when you create a subform, the fields in the subform are divided by a comma. This doesn’t look good on your pages, so to solve this problem, we can override the default subform of Joomla.
To achieve this, you need to create an override for the subform. This can be done by creating a new file in the html folder of your template. Here you can read more about "how do I get a Subform to look better".
Go to System > Site Templates.
Choose your template by selecting it. In this example, we will use the default J4 template “Cassiopeia”, so go into “Cassiopeia Details and Files”.
Select “Create Overrides” > Plugins > fields > subform
You need to open the file in the Joomla Editor located in the “html” folder. Navigate to the file “subform.php” in the folder ”/templates/cassiopeia/html/plg_fields_subform”. The file should look like this:
<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Subform
*
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
defined('_JEXEC') or die;
if (!$context || empty($field->subform_rows))
{
return;
}
$result = '';
// Iterate over each row that we have
foreach ($field->subform_rows as $subform_row)
{
// Placeholder array to generate this rows output
$row_output = array();
// Iterate over each sub field inside of that row
foreach ($subform_row as $subfield)
{
$class = trim($subfield->params->get('render_class', ''));
$layout = trim($subfield->params->get('layout', 'render'));
$content = trim(
FieldsHelper::render(
$context,
'field.' . $layout, // normally just 'field.render'
array('field' => $subfield)
)
);
// Skip empty output
if ($content === '')
{
continue;
}
// Generate the output for this sub field and row
$row_output[] = '<span class="field-entry' . ($class ? (' ' . $class) : '') . '">' . $content . '</span>';
}
// Skip empty rows
if (count($row_output) == 0)
{
continue;
}
$result .= '<li>' . implode(', ', $row_output) . '</li>';
}
?>
<?php if (trim($result) != '') : ?>
<ul class="fields-container">
<?php echo $result; ?>
</ul>
<?php endif; ?>
Now Change the code in line 56 from this:
$result .= '<li>' . implode(', ', $row_output) . '</li>';
To this:
$result .= '<li>' . implode('<span class="field-divider">,</span> ', $row_output) . '</li>';
Then simply put this in "user.css":
.field-divider { display: none; }
- LET ME KNOW IF YOU KNOW ANY OTHER WAYS TO DO THIS IN THE COMMENTS BELOW -