It is an unfortunate fact of life that Moodle uses an archaic, procedural style forms library. In your own plugins you can ignore it to a large extent. However, sometimes it's necessary to add a configuration option, for instance in the course settings form or in your own plugin's settings form. Let's see how to deal with that requirement here.

Add Course Configuration Setting

In this example, we will add a field “invitation” to the standard course settings form. Here, users can fill in the text for an email invitation for the course (how and when this mail gets send is not the topic of this tutorial).

Add the following code to course/edit_form.php, around line 288:

/// Editable text field for email invitation
$mform->addElement('header','mailtext', get_string('header_email_notifications', 'sessionmanagement'));

$mform->addElement('editor','invitation_editor', get_string('sessioninvitation', 'sessionmanagement'));
$mform->addHelpButton('invitation_editor', 'sessioninvitation', 'sessionmanagement');
$mform->setType('invitation_editor', PARAM_RAW);

The code above will add an html editor for your invitation field.

Now, add the following code to course/lib.php, in both functions update_course and create_course. (You can skip this step if your field is not an editor.)

$data->invitation = $data->invitation_editor['text'];

Add the following code to course/edit_form.php, around line 78:

$course->invitation_editor = array('text' => $course->invitation, 'format' => 2); // Plain text format because we want to be able to add variables in the mail text

And finally, don't forget to add a new column invitation to the mdl_course table. To have your own module do that, use the /mod/yourmod/db/install.php file:

// in file /mod/yourmod/db/install.php
function xmldb_yourmod_install() {
    global $DB;

    $dbman = $DB->get_manager();
    $table = new xmldb_table('course');
    $field = new xmldb_field('invitation', XMLDB_TYPE_TEXT, null, null, null, null);
    if (!$dbman->field_exists($table, $field))
        $dbman->add_field($table, $field);

Or in /mod/yourmod/db/upgrade.php:

    if ($oldversion < 2014031100) {
        $table = new xmldb_table('course');
        $field = new xmldb_field('invitation', XMLDB_TYPE_TEXT, null, null, null, null);
        if (!$dbman->field_exists($table, $field))
            $dbman->add_field($table, $field);
        upgrade_mod_savepoint(true, 2014031100, 'yourmod');

Including Your Own JavaScript

Use the static function html_writer::tag to set up your own script element. Here, you can either include a javascript file, or put out the javascript directly.

$script = html_writer::tag('script', '', array("type" => "text/javascript", "src" => $CFG->wwwroot."/mod/rainmaker/scripts/jquery-1.8.2.min.js"));

$mform->addElement('html', $script);

// Output warning if javascript is turned off
$noscript = html_writer::tag('noscript', get_string('noscript', 'rainmaker'), array("class" => "warning"));
$mform->addElement('html', $noscript);


Usually the Moodle forms are composed of 'floaters': div elements with a float:left css styling. If you have other needs, you will have to override the defaults. Exactly how this is done may depend upon your theme of choice. Here's an example where I override the css for a custom form displayed under the Essential theme.

            /* Hide the asterisk (red star) indicating that the field is required */
            .block_contact_form #fitem_id_email .req, .block_contact_form .fdescription.required {display:none;}

            /* move the entire field to the right */
            .block_contact_form #fitem_id_email  { float:right }

            /* The original css is very specific, so in order to override the original css we need to repeat the entire 'path' here */
            .used-region-side-pre.used-region-side-post #region-main .block_contact_form .mform:not(.unresponsive) .fitem .felement  {float:none; width: auto; display: inline-block;}
            .used-region-side-pre.used-region-side-post #region-main .block_contact_form .mform:not(.unresponsive) .fitem .fitemtitle {float:none; width: 60px; display: inline-block;}

            /* We only want the css to apply to this plugin (block contact_form), so we include the css class for this block everywhere */
            .block_contact_form .mform .fitem .felement { float: none; width:auto; display:inline-block; margin-left: 0px; }
            .block_contact_form .mform .fitem .fitemtitle { width:60px; float:none; display:inline-block;  margin-right:10px; }

            body #region-main .block_contact_form .mform:not(.unresponsive) .fitem .felement { float: none; width:auto; display:inline-block; }
            body #region-main .block_contact_form .mform:not(.unresponsive) .fitem .fitemtitle { width:60px; float:none; display:inline-block;  margin-right:10px; }

Processing Date Selectors

To process a date selector (dropdown boxes with a box for the day, month and year), you need to know how to process form post variables of the array type. Here's how you do that:

$startdate = optional_param_array('startdate', array(), PARAM_INT);
$enddate = optional_param_array('enddate', array(), PARAM_INT);

Data-bound HTMLEditor

To set the htmleditor (online text editor), you need to put your html blob in an array with the name of your form field. For instance, if you've got a field “message”, you get the following code:

$value = $questionnaire->message; // $questionnaire is a database record
$questionnaire->message = array();
$questionnaire->message['text'] = $value;
$questionnaire->message['format'] = 1; // 1 => htmleditor
$mform->set_data($questionnaire); // $mform contains your Moodle form object

To save the content of the htmleditor, you need to do the reverse:

$fromform = $mform->get_data()
$questionnaire = new stdClass();
$questionnaire->id = $fromform->id;
$questionnaire->message = $fromform->message['text'];
// do the saving next...

Pre-Populating Your Moodle Form

To fill your Moodle form with data, use this code:

$data = new stdClass();
$data->cmid = $cmid;

Unfortunately, this is of no use if you need to access the data inside your form definition. To get access to your data there, provide it to the constructor as the second argument. Example:

$mform = new local_invitations_settings_form($action = null, $your_data);

Then, inside your form definition, access the code through $this→_customdata:

class local_invitations_settings_form extends moodleform {

    function definition() {
        global $USER, $CFG;

        $mform = $this->_form;

        // etc.
    } // function definition()
} // class local_invitations_settings_form    

Personal Tools