Actions

Difference between revisions of "Creating a custom form field type"

From Joomla! Documentation

(+syntax highlighting)
m (Tutorial:Override JFormFields moved to Overriding JFormFields: Moved page to main namespace because the Tutorial namespace is deprecated)

Revision as of 10:02, 15 January 2011

A new feature in Joomla 1.6 is called JForm which lets you to easily create forms, one part of JForm is JFormFields. JFormFields takes care of all the different fields you can find in a form. JFormFields supports a large selection of fields, see the Standard form field types for in-depth info.

Joomla 1.6 makes it possible to override and/or extend these field types, here is how to do that.

Contents

Step 1: Location of files

  • The default form fields are located in "joomla/libraries/joomla/form/fields/"
  • The overridden fields are usually located in "administrator/components/<name of your component>/models/fields", you can specify this or other path from your code:
JForm::addFieldPath(JPATH_COMPONENT . DS . 'models' . DS . 'fields');
  • The XML files with form fields are usually located in "administrator/components/<name of your component>/models/forms". Use something like the following snippet to specify a path to your forms:
JForm::addFormPath(JPATH_COMPONENT . DS . 'models' . DS . 'forms');

Step 2: Setting up base

The first file to create is your base class. The base class is your starting point for overriding JFormField.

Create a new file called myform.php and place it in the folder administrator/components/<name of your component>/models/fields. Add the following code to the file:

<?php
// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die('Restricted access');
 
abstract class JFormFieldMyForm extends JFormField {
 
        protected $type = 'MyForm'; 
}

Important lines:

  • abstract class JFormFieldMyForm extends JFormField

The name of the file is myform.php this means the name of the class must be the same

  • protected $type = 'MyForm';

The $type must also have the same name as your class

Step 3: Creating a field override

With the base class in place we can now create our field overrides.

Create a new file called mylist.php and place it in the folder administrator/components/<name of your component>/models/fields. Add the following code to the file:

<?php
// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die('Restricted access');
 
jimport('joomla.form.helper');
JFormHelper::loadFieldClass('MyForm');
 
class JFormFieldMyText extends JFormFieldMyForm {
 
        protected $type = 'MyText';
 
        public function getInput() {
                $field = JFormHelper::loadFieldType('Text');
                // Workaround
                $field->setForm($this->form); 
                $field->setup($this->element, $this->value, $this->group);
 
                return $field->getInput();
        }
}

Important lines:

  • JFormHelper::loadFieldClass('MyForm');

Here we load our base class

  • class JFormFieldMyText extends JFormFieldMyForm {

Here we create our override called MyText and make it extend MyForm, our base class. The class name must always be the same as the filename

  • protected $type = 'MyText';

Same as the base class the field class also needs a $type set, this is the same name as your class name

  • public function getInput() {

A field override class must always have the public function getInput()

Notice: This example contains a workaround until bug 21644 (http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=21644) has been fixed.

Grouping custom field types

Custom field types can be grouped by using an underscore in the field name. A field class with a name for example like "JFormFieldMy_randomField" must be stored in "administrator/components/<name of your component>/models/fields/my/randomField.php". We can prefix our form field names with some group name, then we put an underscore and then a name of a field.

Step 4: Using the override field

To use the override field MyText, we need to update the XML file that contains the form fields. Open your XML file located in administrator/components/<name of your component>/models/forms and find a field that is of the type text. This example is from article.xml:

<field name="title" type="text" label="JGLOBAL_TITLE"
        description="JFIELD_TITLE_DESC" class="inputbox" size="30"
        required="true" />

We change this field to look like this:

<field name="title" type="MyText" label="JGLOBAL_TITLE"
        description="JFIELD_TITLE_DESC" class="inputbox" size="30"
        required="true" />

Notice how type="text" changed to type="MyText". The MyText here refers to the class made in step 3. The type name is cAsE-sEnSiTiVe.

With these changes in place, your override is done and ready to use.

Overriding getLabel()

There are 2 ways of overriding the getLabel() method:

  1. Wrap it in your own tags
  2. Modify it completely

Wrapping the label

To wrap a form label you can add the following function to your myform.php file:

public function getLabel() {
     return '<span style="text-decoration: underline;">' . parent::getLabel() . '</span>';
}

This code will underline your form labels.

Writing your own label

To write your own label you can add the following function to your myform.php file:

public function getLabel() {
        // Initialize variables.
        $label = '';
        $replace = '';
 
        // Get the label text from the XML element, defaulting to the element name.
        $text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
 
        // Build the class for the label.
        $class = !empty($this->description) ? 'hasTip' : '';
        $class = $this->required == true ? $class.' required' : $class;
 
        // Add replace checkbox
        $replace = '<input type="checkbox" name="update['.$this->name.']" value="1" />';
 
        // Add the opening label tag and main attributes attributes.
        $label .= '<label id="'.$this->id.'-lbl" for="'.$this->id.'" class="'.$class.'"';
 
        // If a description is specified, use it to build a tooltip.
        if (!empty($this->description)) {
                $label .= ' title="'.htmlspecialchars(trim(JText::_($text), ':').'::' .
                                JText::_($this->description), ENT_COMPAT, 'UTF-8').'"';
        }
 
        // Add the label text and closing tag.
        $label .= '>'.$replace.JText::_($text).'</label>';
 
        return $label; 
}

This example will add a checkbox before the label.