How to Get Form in Joomla Component

The Form class of Joomla is used to create complex forms with flexible layouts and dynamic properties. First, the form fields are defined in the XML file. Then, the view file gets the form from the model and layout file displays the form.

Step 1: XML Form File

admin/forms/planet.xml

At present, we are adding only title field.

<?xml version="1.0" encoding="utf-8"?>
<form>
    <field 
        name="title" 
        type="text" 
      label="JGLOBAL_TITLE" 
        required="true" />
</form>

Similarly, other fields can be added to the form.

Step 2: View File

src/View/Planet/HtmlView.php

In the view file, get the form from the model in the display() method.

namespace TechFry\Component\Planets\Administrator\View\Planet;

defined('_JEXEC') or die;

use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
use Joomla\CMS\Toolbar\Toolbar;
use Joomla\CMS\Toolbar\ToolbarHelper;
use Joomla\CMS\Language\Text;

class HtmlView extends BaseHtmlView
{
    public $form;
    
    public function display($tpl = null) 
    {
        $this->form = $this->get('Form');
      
        $this->addToolBar();
        
        parent::display($tpl);
    }
    
    protected function addToolBar()
    {
        ToolbarHelper::title(Text::_('COM_PLANETS_PLANET_ADD'));
     
        ToolbarHelper::apply('planet.apply');
    }
}

This file is similar to the view file added earlier for the "Planets" view. The code will look for the method getForm() in the model file.

In the toolbar, we are adding the title and "Save" button. The save button (planet.apply) will send the submitted form to the apply() method of the planet controller.

Step 3: Model File

You need to extend the model class with the AdminModel. The AdminModel class extends FormModel class.

The getForm() method gets the Form object for the edit form.

namespace TechFry\Component\Planets\Administrator\Model;

defined('_JEXEC') or die;

use Joomla\CMS\MVC\Model\AdminModel;

class PlanetModel extends AdminModel
{
    public function getForm($data = array(), $loadData = true)
    {
        $form = $this->loadForm('com_planets.planet', 'planet', array('control' => 'jform', 'load_data' => $loadData));

        if (empty($form))
        {
            return false;
        }
        
        return $form;
    }
}

The loadForm() and preprocessForm() methods are defined in the FormModel class and the bind() method is defined in the Form class. The first argument (name) of loadForm() is set to "com_planets.planet". The second argument (source), is "planet", and the third argument is the associative array for options.

The form is defined in the source file: forms/planet.xml

After you have set the $form variable with the Form object, you check to see if you are loading data to the form. If you want to pre-load data for the form, you include an element called "load_data" that is set to a boolean true. 

Then, you execute the loadFormData() method. This method gets any previously loaded data from the session. Normally, this is empty.

If you are editing an item for the first time or creating a new item, you call $this->getItem(), which creates a JObject with the fields for the form. If you have an existing item, you get the data for that item. For a new item, you get the default values or, if no default is specified in the field, you get an empty value.

Suppose the user has filled out the form to add a new item but has some invalid data in the form. In this case, the save will not be successful, so the data is not saved in the database. It would be very frustrating if the user had to reenter all the fields to fix a single error. To handle this scenario, you save the entered data in the user’s session. Only after the save is successful, you clear this out of the session.

So, you either have data from the database, which you can get with getItem(), or you have data from the session, which you can get with getUserState().

Modifying Form Dynamically

Inside the getForm() method, before return $form, you can modify the form with many methods of the Form class. You can easily fine-tune your forms dynamically before they are rendered.

Step 4: Layout File - Rendering Form

tmpl/planet/edit.php

After you get the form in the view file ($this->form), the form is rendered in the layout file (edit.php).

use Joomla\CMS\HTML\HTMLHelper;

$wa = $this->document->getWebAssetManager();

$wa->useScript('keepalive');
$wa->useScript('form.validate');
?>
<form action="<?php echo JRoute::_('index.php?option=com_planets&layout=edit&id=' . (int) $this->item->id); ?>"
method="post" name="adminForm" id="item-form" class="form-validate">

    <?php echo $this->form->renderField('title'); ?>
    
    <input type="hidden" name="task" value="planet.edit" />
    <?php echo HTMLHelper::_('form.token'); ?>
</form>

The renderField() method of the Form class displays the field - both label and input. When the form is submitted, the data is sent to the controller depending upon the action buttons in the toolbar.