Working with Joomla Forms - Form Class

Form fields (like text, textarea, radio, select/list) are fields in a HTML <form> element. In Joomla, you can use the Form class to conveniently and flexibly create forms with a large amount of form fields. These form fields are defined in XML file.

For example, in the component the XML file is stored in the folder: forms/form_name.xml

1. Get Joomla Form Class

First, you need to get an instance of a form.

use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormFactoryInterface;

$form = Factory::getContainer()->get(FormFactoryInterface::class)->createForm('myform', array('control' => 'jform'));

The above code creates a Form instance with the name "myform". An array with control as jform is also passed. The HTML input elements will have name attributes set to "jform[message]", "jform[email]", and so on.

2. Load XML File

Next, load in the XML file containing the form definition.

$form->loadFile(JPATH_SITE . '/components/com_example/forms/myform.xml');

Alternatively, you can create a SimpleXMLElement in your code and then call

$form->load($xml);

The Joomla code for loadFile() just reads the data from the file into a SimpleXMLElement variable and then calls load().

3. Provide Pre-fill Data

If the form is being used to edit a record in the database or you need to prefill user related information like name and email, you can provide values by setting up an associative array $data. 

$form->bind($data);

4. Output the Form

1. To display or render the field (both label and input):

echo $form->renderField($field_name);

2. To display only input of the field:

echo $form->getInput('field_name');

This is a method to get a form field markup for the field input. It will not display the control group and label.

3. To display only label of the field:

echo $form->getLabel('field_name');

This is a method to get the label for a field input.

4. The XML form can have many field sets. Each field set can contain many fields. You can display or render complete field set.

echo $form->renderFieldset('fieldset_name');

5. Change Forms Dynamically

If you have defined your form statically in an XML file, then after it is loaded, you can modify it dynamically in the PHP code.

1. Add field set

To create a new fieldset dynamically, create a SimpleXMLElement and the load it to the form.

$xml = new \SimpleXMLElement('<form><fieldset name="query" label="Query"></fieldset></form>');
$form->load($xml);

2. Add fields

You can use setField() to add or replace a single field.

$element = '<field name="title" type="text" label="Title" />';
$xml = new \SimpleXMLElement($element);
$form->setField($xml, $group, $replace, $fieldset);

Specify the $group and $fieldset parameters to include the new field within a specific field group and fieldset. The default group is null and default fieldset is "default".

If the $replace flag is set to true, then the field will be set whether it already exists or not. If false, then the field will not be replaced if it already exists. The default value of replace is true.

3. Add multiple fields

You can use setFields() to add or replace several fields. you can define an array of XML elements and pass these to the setFields(), which is the equivalent of calling setField() on each of the individual elements.

4. Set field attributes

You can use setFieldAttribute() to set or amend an attribute associated with a field.

$form->setFieldAttribute('field_name', 'attribute_name', 'attribute_value');

This is a method to set an attribute value for a field XML element. Attribute refers to the Joomla field attribute, rather than the HTML attribute of the input element.

5. Set field value

The HTML value attribute is treated differently from other HTML attributes. You can use the bind() to set the value or directly using the setValue() method.

$form->setValue('field_name', null, 'field_value');

This is a method to set the value of a field. If the field does not exist in the form, then the method will return false. The second argument is for field group.

6. Remove field or group

You can remove fields from the Form by calling removeField() to remove a specific field or removeGroup() to remove all the fields within a specified field group.

$form->removeField('field_name');

You can remove any field by name before displaying the form.

6. Other Methods of Form Class

There are a number of methods which allow you to access various aspects of the Form.

1. Form Name

To get the name of the form:

echo $form->getName();

2. Form Control

To get the form control:

echo $form->getFormControl();

3. Form Data

The getData() returns the pre-fill data (as json string) which has been set using the Form bind() method.

echo $form->getData();

4. Field Attribute

To get the attribute value of any field from the Form object.

echo $form->getFieldAttribute('field_name', 'attribute_name');

You can also get the attribute from the FormField object.

5. Field set

To get all the fieldsets

$fieldsets = $form->getFieldsets();

This is a method to get an array of fieldset objects with properties which reflect the <fieldset> tag in the form definition file like name, label and description.

6. Fields

The methods getField(), getFieldset() and getGroup() return fields as Joomla FormField objects. Then, you can use FormField class methods. For example,

$fields = $form->getFieldset('fieldset_name');

Now, to display input or label or display control group with label and input:

foreach($fields as $field)
{
 echo $field->input;
 echo $field->label;
 echo $field->renderField();
}

To get one field:

$field = $form->getField('field_name');

This is a method to get a form field represented as a FormField object. You can also access field attributes like $field->name, $field->label and so on.

7. Methods of FormField Class

You can use following methods after getting FormField objects using any of the getField(), getFieldset() and getGroup() methods.

1. Getter and Setter

To get or set the value of attributes and parameters:

echo $field->__get('attribute_name');
$field->__set('attribute_name', 'attribute_value');

2. Attribute value

To get attribute value from the XML field definition:

echo $field->getAttribute('attribute_name');

3. Display field

To display or render field (control group with label and input):

echo $field->renderField();

How To Create XML Form: myform.xml

Following is the example of XML form. You can add more fields in the fieldset or create new fieldset.

<?xml version="1.0" encoding="UTF-8"?>
<form class="form-validate">
<fieldset name="fieldset_name">
<field name="name" type="text" label="Name" />
</fieldset>
</form>

Display Form Using Loop

You can display multiple field sets using loops.

foreach ($form->getFieldsets() as $fieldset) 
{
$fields = $form->getFieldset($fieldset->name);
if (count($fields))
{
foreach ($fields as $field)
{
echo $field->renderField();
}
}
}

You are not required to change the code even if the names of field set or names of fields changes.