Trying to add a custom form element type

Trying to add a custom form element type

by Mark Oxley -
Number of replies: 1

I'm having trouble adding a custom form element to my plugin. Essentially, it uses an existing element type, with custom HTML to be output before it. Here is a minimal example of my code:

local/my_plugin/classes/form/custom_text_input.php:

<?php
namespace local_my_plugin\form;

defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/form/text.php');

class custom_text_input extends \MoodleQuickForm_text
{    
    /**
     * Constructor
     */
    public function __construct($elementName=null, $elementLabel=null, $options=null, $attributes=null)
    {
        parent::__construct($elementName, $elementLabel, $options, $attributes);
    }

    /**
     * Returns HTML for the form element
     *
     * @return string
     */
    function toHtml()
    {
        $html = 'Custom text';
        $html .= parent::toHtml();

        return $html;
    }
}

local/my_plugin/classes/form.php:

<?php
namespace local_my_plugin;

use \html_writer;
require_once("$CFG->libdir/formslib.php");
class form extends \moodleform
{
    public function definition()
    {
        global $CFG;
        \MoodleQuickForm::registerElementType(
            'custom_text_input',
            "$CFG->dirroot/local/my_plugin/classes/form/custom_text_input.php",
            'local_my_plugin\form\custom_text_input'
        );
        $mform = $this->_form; // Don't forget the underscore! 
        $mform->addElement('custom_text_input', 'name', 'Test Element');
    }
}


What am I doing wrong? Why is only the input element showing up, and not the 'Custom text' which is applied before it in the toHtml() function?
Average of ratings: -
In reply to Mark Oxley

Re: Trying to add a custom form element type

by Vitaly Potenko -
Picture of Core developers Picture of Plugin developers
That's because the 'toHtml()' method isn't used by Moodle to render a QuickForm element actually. Moodle uses the Mustache templating engine to render the form elements from the time Mustache had been introduced to Moodle. Take a look at the 'text' element class which you're extending, you'll see that it implements the 'templatable' interface. Then, in formslib.php find the 'MoodleQuickForm_Renderer' class and it's method 'renderElement()'. In it's turn it calls the 'mform_element()' method of the core renderer. And it's where all the things happen, you'll see it from the source code.
By the way, it makes things a bit complicated when implementing a custom form element. The renderer looks for templates in core folder only by default and it's hardcoded. To add a custom template for your custom element you'll have to override this logic.