How to Get Form in Front End

A form to the site frontend allows users to submit information that can be saved to the database or sent to emails. For example, frontend forms in Joomla are used to create article (com_content), contact form (com_contact), user registration form (com_users).

To create a form on the frontend, you need:

  1. XML file for the form definition
  2. View file - which is called "form".
  3. Layout file, associated with the form view - which is called "edit".
  4. Model file - which is also called "form", to align with the view.
  5. Controller file - to handle form submissions

Then, you need to handle the HTTP POST requests when the user submits the form.

This functionality is similar to adding form in the backend. Also, refer to Form class of Joomla to display form in the layout file.

Classes

  • The Model class will extend AdminModel which supports forms and saving records to the database. Even though it's called AdminModel, it is still available at the site part.
  • The controller class will extend FormController.

1. XML Form

First, create a new form (planet.xml) in the forms subdirectory.

site/forms/planet.xml

<?xml version="1.0" encoding="UTF-8"?>
<form>

    <fieldset name="general">

        <field
            name="id"
            type="hidden"
            label="ID"
            default="0"
            readonly="true" />

        <field
            name="title"
            type="text"
            label="JGLOBAL_TITLE"
            required="true" />

        <field
            name="description"
            type="editor"
            label="Description" />

        <field
            name="published"
            type="list"
            label="JSTATUS"
            class="form-select-color-state"
            default="1"
            validate="options">
            <option value="1">JPUBLISHED</option>
            <option value="0">JUNPUBLISHED</option>
            <option value="2">JARCHIVED</option>
            <option value="-2">JTRASHED</option>
        </field>

    </fieldset>

</form>

We have added four fields - id (hidden), title, description and published status. You can add more fields as required.

2. View File

site/src/View/Horm/HtmlView.php

The view file calls the Model file for the form.

class HtmlView extends BaseHtmlView
{
    protected $form;
    
    protected $item;

    public function display($tpl = null)
    {
        $this->item = $this->get('Item');
        $this->form = $this->get('Form');

        parent::display($tpl);
    }
}

It will look for the methods getForm() and getItem() in the Model class.

3. Model File

site/src/Model/FormModel.php

The model is similar to the admin equivalent.

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

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

return $form;
}

The first argument in the loadForm() is the name which is set to component_name.view_name. The second argument is the source of form which is the name of XML file (planet.xml).

As the name of the Model (which is Form) is different from the name of the Table (which is Planet as defined in the admin part), you also need to define the getTable() method.

public function getTable($name = 'Planet', $prefix = 'Administrator', $options = [])
{
    return parent::getTable($name, $prefix, $options);
}

4. Layout File

site/tmpl/form/edit.php

You display the actual form in the layout file.

<h1>Planet Form</h1>
<form action="<?php echo Route::_('index.php?option=com_stars&id=' . (int) $this->item->id); ?>" method="post">
    <?php echo $this->form->renderFieldset('general'); ?>

    <button type="submit" class="btn btn-primary">
        <?php echo Text::_('JSAVE'); ?>
    </button>

    <input type="hidden" name="option" value="com_stars">
    <input type="hidden" name="task" value="planet.save">
    <?php echo HTMLHelper::_('form.token'); ?>
</form>

After clicking on submit or save button, the data will be sent to the save() method in the Planet Controller.

5. Controller File

site/src/Controller/PlanetController.php

This controller is similar to the admin part. This class contains methods used for processing of the form.

public function save($key = null, $urlVar = null)
{
    $this->checkToken();

    $app = $this->app;
    $model = $this->getModel('Form');
    $table = $model->getTable();
    $data = $this->input->post->get('jform', [], 'array');
    $context = "$this->option.edit.$this->context";

    if (empty($key)) 
    {
        $key = $table->getKeyName();
    }

    if (empty($urlVar)) 
    {
        $urlVar = $key;
    }

    $recordId = $this->input->getInt($urlVar);

    $data[$key] = $recordId;

    if (!$model->save($data))
    {
        $app->setUserState($context . '.data', $data);

        // Redirect back to the edit screen
        $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error');

        $this->setRedirect(Route::_('index.php?option=' . $this->option . '&view=form&layout=edit' . $this->getRedirectToItemAppend($recordId, $urlVar), false));

        return false;
    }

    $this->setMessage('Form successfully saved.');

    $this->setRedirect(Route::_('index.php?option=' . $this->option . '&view=planets', false));

    return true;
}

Since the name of the Controller is Planet, we get the Form Model to save the record. Then, we get the primary key column for the table and get the record id. The $data is array that contains the information submitted by the user.

6. Menu File

site/tmpl/form/edit.xml

Create the menu file, so you can create a menu item for inserting new records from the frontend.

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
    <layout title="Planet Form">
        <message>Displays a form for Planet.</message>
    </layout>
</metadata>