TLDR: You need to used FieldsHelper::render for that.
Here are the code samples:
fancysubform.php : the subform custom layout
Place this file there:
YOUR_JOOMLA_WEBSITE_ROOT/templates/cassiopeia/html/layouts/com_fields/field/fancysubform.php
<?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
* @contributor Alexandre ELISÉ <[email protected]> Modified version on 2021-12-08
* @description The content of this file needs to be copied in
* YOUR_JOOMLA_WEBSITE_ROOT/templates/cassiopeia/html/layouts/com_fields/field/fancysubform.php
*/
use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
defined('_JEXEC') or die;
if (!array_key_exists('field', $displayData))
{
return;
}
$field = $displayData['field'];
$context = $field->context;
if (!$context || empty($field->subform_rows))
{
return;
}
// remember you don't use prefix or suffix in your subform custom field so use it for something useful
$subformContainerClass = $field->params->get('prefix', '');
$subformResultClass = $field->params->get('suffix', '');
$result = '';
// Iterate over each row that we have
foreach ($field->subform_rows as $subform_row)
{
// Placeholder array to generate this rows output
$row_output = [];
// 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'
['field' => $subfield]
)
);
// Skip empty output
if ($content === '')
{
continue;
}
// Generate the output for this sub field and row
$row_output[] = '<div class="field-entry' . ($class ? (' ' . $class) : '') . '">' . $content . '</div>';
}
// Skip empty rows
if (count($row_output) == 0)
{
continue;
}
$result .= sprintf('<div class="fields-result %s">%s</div>', ($subformResultClass ? (' ' . $subformResultClass) : ''), implode('', $row_output));
}
?>
<?php if (trim($result) != '') : ?>
<div class="fields-container <?php echo($subformContainerClass ? (' ' . $subformContainerClass) : ''); ?>">
<?php echo $result; ?>
</div>
<?php endif; ?>
The subform styling
user.css
Place this file there:
YOUR_JOOMLA_WEBSITE_ROOT/templates/cassiopeia/css/user.css
/*
* Subform custom field styling
* This file needs to be in YOUR_JOOMLA_WEBSITE_ROOT/templates/cassiopeia/css/user.css
*/
.fancy-result.fancy-bio {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
justify-items: center;
border: 1px solid #ededed;
max-width: 25vw;
background-color: var(--fancy-secondary-color);
backdrop-filter: brightness(2%);
padding: 0.5rem;
border-radius: 0.5rem;
}
.field-entry.fancy-render.fancy-firstname,
.field-entry.fancy-render.fancy-lastname,
.field-entry.fancy-render.fancy-phone
{
display: grid;
grid-template-columns: 6rem 1fr;
grid-template-rows: auto;
align-items: center;
width: 100%;
}
.fancy-label {
background-color: coral;
color: black;
margin: 2px;
padding: 2px;
border-radius: 2rem;
max-width: 6rem;
max-height: auto;
text-align: center;
}
.fancy-value.fancy-photo img {
border-radius: 50%;
max-width: 100%;
max-height: 100%;
}
span.field-value.fancy-value.fancy-firstname,
span.field-value.fancy-value.fancy-lastname,
span.field-value.fancy-value.fancy-phone {
text-align: center;
color: white;
}
The actual minimal article layout override to get this done. Here it is:
Place this file:
YOUR_JOOMLA_WEBSITE_ROOT/templates/cassiopeia/html/com_content/article/fancysubformarticlelayoutoverride.php
Then choose this layout for the article that has the subform custom field
`<?php
declare(strict_types=1);
/**
* Subform Custom Field Manual Rendering
*
* @version 0.1.0
* @package fancysubformlayoutoverride.php
* @author Alexandre ELISÉ <[email protected]>
* @copyright (c) 2009-2021 . Alexandre ELISÉ . Tous droits réservés.
* @license GPL-2.0-and-later GNU General Public License v2.0 or later
* @link https://alexapi.cloud
* @description this file should be placed in
* YOUR_JOOMLA_WEBSITE_ROOT/templates/cassiopeia/html/com_content/article/fancysubformarticlelayoutoverride.php
* Then choose this layout for the article with the subform custom field
*
*/
use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
defined('_JEXEC') || die;
// minimum code to render manually a custom field in an article
// based on it's name rather than on it's id
$customFields = $this->item->jcfields;
// custom fields by id ]
// not that useful in this case since jcfields is already indexed by id
//$customFieldsById = ArrayHelper::pivot($customFields, 'id');
//$subformCustomField = $customFieldsById[13];
// OR (uncomment the one you wanna use)
// custom fields by name
//$customFieldsByName = ArrayHelper::pivot($customFields, 'name');
//$subformCustomField = $customFieldsByName['article-bio'];
// the default layout of custom field
// you can specify here your own layout
// for example: field.fancysubform
// but you will first need to create that layout in
// YOUR_JOOMLA_WEBSITE_ROOT/templates/YOUR_TEMPLATE/html/layouts/com_fields/field/fancysubform.php
// if you want a basis copy paste the content of
// YOUR_JOOMLA_WEBSITE_ROOT/components/com_fields/layouts/field/render.php
$computedLayout = sprintf('field.%s', $customFields[13]->params->get('layout', 'render'));
echo FieldsHelper::render('com_content.article', $computedLayout, ['field' => $customFields[13]]);``
Here is the link to the related gist: The source code on GitHub
A screenshot of the result I got locally as an example
var_dump($this->item->jcfields[X]);
for a repeated field? If nothing, how aboutvar_dump($this->item);
? These are some basic technique which you can use to improve your own understanding.