Custom field type in Joomla 5

I’m trying to create a plugin that adds a file type field with support for dropzone and other functions to user fields. Plugin structure:

/plugins/fields/upload/
    /fields
        upload.php
    /params
        upload.xml
    /services
        provider.php
    /src
        /Extension
            Upload.php
    /tmpl
        upload.php
    upload.xml

The problem is that the function getInput() is not executed in /fields/upload.php I added the echo output to the end of the file for the test - it works. File contents /fields/upload.php:

<?php    
namespace Joomla\Plugin\Fields\Upload\Fields;

use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormField;

defined('_JEXEC') or die;

class UploadField extends FormField
{
    protected $type = 'Upload';

    protected function getInput()
    {

        return '<input type="file" name="' . htmlspecialchars($this->name) . '" />';
    }
}

echo '1111';

File contents /src/Extension/Upload.php:

namespace Joomla\Plugin\Fields\Upload\Extension;

use Joomla\CMS\Factory;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Form\Form;
use Joomla\Component\Fields\Administrator\Plugin\FieldsPlugin;
use Joomla\Event\SubscriberInterface;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

final class Upload extends FieldsPlugin implements SubscriberInterface
{
    public function onCustomFieldsPrepareDom($field, \DOMElement $parent, Form $form)
    {
        $fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);

        if ($field->type !== 'upload') {
            return;
        }

        if (!$fieldNode) {
            return $fieldNode;
        }

        //$form->addFieldPath(JPATH_PLUGINS . '/fields/upload/fields');

        $doc = Factory::getDocument();
        $doc->addStyleSheet(Uri::root() . 'media/plg_fields_upload/css/dropzone.min.css');
        $doc->addScript(Uri::root() . 'media/plg_fields_upload/js/dropzone.min.js');

        $fieldNode->setAttribute('field_id', $field->id);
        $fieldNode->setAttribute('type', 'upload');
        //$fieldNode->setAttribute('layout', $field->params->get('form_layout', 'upload'));

        return $fieldNode;
    }
}

I have not found any documentation on creating custom types. What could be the problem?

Problem Summary

Your custom getInput() method in /fields/upload.php is not being executed, even though the file is being loaded (you confirmed via echo '1111').


Why It Fails

Joomla doesn’t auto-load custom field types unless you explicitly tell it where to find them. You need to register the path to your custom field in your plugin code.


Solution – Register the Field Path

In your plugin’s onCustomFieldsPrepareDom() method, add this line:

$form->addFieldPath(JPATH_PLUGINS . '/fields/upload/fields');

Uncomment it — this is required to make Joomla aware of your custom UploadField.

So your method should be:

public function onCustomFieldsPrepareDom($field, \DOMElement $parent, Form $form)
{
    $fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);

    if ($field->type !== 'upload') {
        return;
    }

    if (!$fieldNode) {
        return $fieldNode;
    }

    //  Register the custom field class path
    $form->addFieldPath(JPATH_PLUGINS . '/fields/upload/fields');

    //  Add assets
    $doc = Factory::getDocument();
    $doc->addStyleSheet(Uri::root() . 'media/plg_fields_upload/css/dropzone.min.css');
    $doc->addScript(Uri::root() . 'media/plg_fields_upload/js/dropzone.min.js');

    //  Set attributes
    $fieldNode->setAttribute('field_id', $field->id);
    $fieldNode->setAttribute('type', 'upload');

    return $fieldNode;
}

Why This Fix Works

Joomla’s form system doesn’t scan all plugins for custom field types. You must manually register the directory containing your custom FormField classes with $form->addFieldPath().


Extra Tip

Also make sure your XML field definition uses:

<field name="..." type="upload" ... />

And that upload.php defines the class with this exact match:

protected $type = 'Upload'; // Must match type in XML (case-sensitive)