0

When creating custom layout overrides the PHP code <?php echo $this->item->jcfields[X]->value; ?> Works successfully, but does not function at all when it comes to repeatable subform fields.

  1. What is the correct PHP to use to render subforms/repeatable fields on the frontend,
  2. Accordingly how would I edit my HTML in the override to account for how the subform will render?
1
  • I don't have a Joomla project open to investigate. Out of curiosity, what do you see when you var_dump($this->item->jcfields[X]); for a repeated field? If nothing, how about var_dump($this->item);? These are some basic technique which you can use to improve your own understanding. Commented Nov 27, 2021 at 10:58

1 Answer 1

1

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

Screenshot of the subform custom field rendered manually using php and css

1
  • 1
    Alex for the win, once again.
    – Malkio
    Commented Dec 10, 2021 at 18:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.