LOGIC Library

This site is the Logic involvement in sharing expertise and skills acquired in daily work. The goal is to create a solid knowledge base and share best practices in software development and systems management.

More info about us can be found on logicsistemi.it.

Developing MVC components for Joomla! 2.5 - Part 8

With this post we finally complete our example in terms of functionality, adding the functions for creating and editing records.

To do this we introduce a new view and Joomla! forms (JForm), although this aspect, due to its complexity, will be analyzed only superficially.

The model for the modification

Let's come back to the model RegistryModelPerson defined in the file person.php into model folder.

If you remember we declared a method getForm, needed to impled the abstract method from the parent class and avoid any error during execution.

This method is inherited from JModelAdmin, class that implements methods for insert and delete from the database, which in turn inherits from JModelForm. This class provides methods that allow us to define the fields to show in our form using a special XML file. This capability is complemented with additional features that allow the creation of custom fields and support data validation into the form.

We modify the model in this way:

<?php
defined('_JEXEC') or die();
jimport( 'joomla.application.component.modeladmin' );
class RegistryModelPerson extends JModelAdmin
{    
    public function getForm($data = array(), $loadData = true)
    {
        // Get the form
        $form = $this->loadForm('com_registry.person', 'person', 
           array('control' => 'jform', 'load_data' => $loadData));
        if (!$form) {
            return false;
        } else {
            return $form;
        }
    }
    public function loadFormData()
    {
        // Load form data
        $data = $this->getItem();
        return $data;
    }
}

The getForm method, in fact, simply call the method loadForm, passing to it, the following parameters:

  • The name of the form. If I understand correctly this name is used to store informations in an internal structure in order to avoid multiple reloading of the same data. Probably just an optimization mechanism, however it is good that the name given is unique in Joomla!, so we also use the component name to complete it.
  • The XML source. This is normally the name of the XML file that will be loaded from a special folder (in this case person.xml). It 's also possible to specify the XML code for the form by setting the following parameters appropriately
  • An array of options. The options are about the control, which will act on the names of the various HTML controls, which will be in the form jform[fieldname], and a parameter, load_data, which specifies whether the value of the fields must be populated (edit) or empty (insert) . In the case of editing data are populated by calling the function loadFormData.

loadFormData function is very simple and uses getItem, that we already know, to retrieve data from the database.

Form definition

I said that the form is defined by an XML file. Let's create, within the models directory, the folder forms and, within it, the file person.xml with the following content.

<?xml version="1.0" encoding="UTF-8"?>
<form>
    <fieldset>
        <field 
            name="id" 
            type="hidden" />
        <field 
            name="name" 
            type="text" 
            label="NAME"
            size="40"
            class="inputbox" />
        <field 
            name="surname" 
            type="text" 
            label="SURNAME"
            size="40"
            class="inputbox" />
    </fieldset>
</form>

As can be seen is defined the list of fields (called "field"), with the respective name, type, label and a number of options that depend on the type.

The name must match the field name in the database, while regarding the type, you can find here a list of controls which Joomla! provides natively.

View and template for the form

Last step: we create the view and its template to display the form.

Inside the folder views let's create the new folder person and, inside it, the tmpl folder. Inside the folder person we create the file view.html.php with the following content.

<?php
// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die();
jimport( 'joomla.application.component.view' );
class RegistryViewPerson extends JView
{
    function display($tpl = null)
    {
        // Get data from the model
        $item = $this->get( 'Item' );
        $form = $this->get( 'Form' );
        $isNew = ($item->id < 1);
        // Disable main menu
        JRequest::setVar('hidemainmenu', true);
        // Toolbar
        if ($isNew) {
            JToolBarHelper::title( JText::_( 'INSERIMENTO' ), 'generic.png' );
        } else {
            JToolBarHelper::title( JText::_( 'MODIFICA' ), 'generic.png' );
        }
        JToolBarHelper::apply('person.apply');
        JToolBarHelper::save('person.save');
        JToolBarHelper::save2new('person.save2new');
        JToolBarHelper::cancel('person.cancel', $isNew ? 'JTOOLBAR_CANCEL' : 'JTOOLBAR_CLOSE');
        $this->item = $item;
        $this->form = $form;
        parent::display($tpl);
    }
}

It should now be clear how the code is working, but we highlight some aspects.

  • Data are retrived by the method getItem. This may not be necessary, but in the template we need the value of the id field and this is the simple way to get it
  • The form is recovered, in the form of an object. We'll need some methods of it
  • The toolbar is built by setting a different title, depending on whether we are in editng or creation
  • They're added some buttons that allow us to save data remaining on the same page, going back to the list, save them by creating a new record or cancel the editing or adding operation. All these operations are taken from Joomla! standards and, as we shall see, thery are already managed by our controller.

Now to the template. Create the file edit.php into the tmpl folder, with the following contents:

<?php 
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

$option = JRequest::getCmd('option');

JHtml::_('behavior.tooltip');
JHtml::_('behavior.formvalidation');
?>
<form action="index.php" method="post" name="adminForm" id="person-admin-form" class="form-validate">
    <input type="hidden" name="option" value="<?=$option?>" />
    <input type="hidden" name="task" value="" />
    <input type="hidden" name="id" value="<?=$this->item->id?>" />
    <?php echo JHtml::_('form.token'); ?>
    
    <fieldset class="adminform">
        <legend><?=JText::_( 'DETAILS' ); ?></legend>
        <ul class="adminformlist">
<?    foreach ($this->form->getFieldset() as $field) { ?>
            <li><?=$field->label?><?=$field->input?></li>
<?    } ?>
        </ul>
    </fieldset>
</form>

All things we already know, except the call to getFieldset, which returns an array with the fields defined above and with properties that are able to generate the needed HTML code. This is very convenient, especially because adding or removing fields nedd only a change to the XML file, the only place where fields are defined.

In addition it was added the hidden id field. This is someway a duplicate, but it's needed because the form rename it as jform[id] and it couldn't be identified when we try to save data.

Pay attention to the template, in this case it isn't called default.php, but edit.php. This choice, standard to Joomla!, is related to the fact that default should be for display, edit for editing. In this way we can hold 2 different templates to be used on the same view based on the action required or permitted to the user. This is very usefull especially in the public part of the website.

The controller

All the remaining code is implemented by Joomla! and, in particular, the controller defined in person.php has already methods to save data and make the appropriate redirects based on the selected task. This method calls the save method of the model, which provides to use the table to store data into the database.

A behind the scenes complicated, but anything to write for us, except for one small thing that can be usefull for people that don't write code using english names...

Joomla! speaks English and, after saving a record, to return to the list, is expect to call a view that has the same name as the editing one but in its plural form. If plurals in your language are not created by adding an s to the end of the word this should not work in the right way. For example in italian person is persona and persons become persone, not personas!

We need to make a tiny change to specify how the controller can call the list view and this is done by modifying the controller RegistryControllerPerson as follows:

<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla controlleradmin library
jimport('joomla.application.component.controllerform');
class RegistryControllerPerson extends JControllerForm
{
    public function __construct($config = array())
    {
        $this->view_list = 'persons';
        parent::__construct($config);
    }
}

Our example is in English and this definition can be avoided: for person Joomla! can build the right plural!

Creating the package

The structure on our PC will now be the following (I added some index.html file I forgot in the previous examples):

com_registry
  admin
    controller.php
    index.html
    registry.php
    controllers
      index.html 
      person.php 
      persons.php 
    models
      forms
        index.html 
        person.xml 
      index.html 
      person.php 
      persons.php 
    sql 
      index.html 
      install.sql 
      uninstall.sql 
      updates 
        index.html 
        0.0.4.sql 
        0.0.5.sql 
        0.0.6.sql 
        0.0.7.sql 
    tables
      index.html 
      person.php 
    views
      index.html 
      person
        index.html 
        view.html.php 
        tmpl
          edit.php 
          index.html 
      persons
        index.html 
        view.html.php 
        tmpl 
           default.php 
           index.html 
  site
    registry.php 
    index.html 
  registry.xml

While the file registry.xml must be modified in the following way:

<?xml version="1.0" encoding="UTF-8"?>
<install type="component" version="2.5.0" method="upgrade">
    <name>Registry</name>
    <author>Edy Incoletti</author>
    <authorEmail>edy.incoletti@logicsistemi.it</authorEmail>
    <authorUrl>http://library.logicsistemi.it</authorUrl>
    <creationDate>March 2012</creationDate>
    <version>0.0.7</version>
    <description>Registry management for the tutorial.</description>
    
    <files folder="site">
        <filename>index.html</filename>
        <filename>registry.php</filename>
    </files>

    <install folder="admin">
        <sql>
            <file charset="utf8" driver="mysql">sql/install.sql</file>
        </sql>
    </install>
    <uninstall folder="admin">
        <sql>
            <file charset="utf8" driver="mysql">sql/uninstall.sql</file>
        </sql>
     </uninstall>
    <update>
        <schemas>
            <schemapath type="mysql">sql/updates</schemapath>
        </schemas>
    </update>

    <administration>
        <files folder="admin">
            <filename>index.html</filename>
            <filename>registry.php</filename>
            <filename>controller.php</filename>
            <folder>controllers</folder>
            <folder>models</folder>
            <folder>sql</folder>
            <folder>tables</folder>
            <folder>views</folder>
        </files>
    </administration>
</install>

Compared to the previous version was just updated the version number.

As usual you can install the package using your package or whatever you find here .

In the next post we will arrange some details and, in particular, will address the mechanism of localization, seen as ability to tranlslate your package in different languages.

Comments   

 
#1 Joe Hildreth 2013-03-24 05:59
If I create a custom form field, can I pass data to the getInput() function?
Quote
 
 
#2 Edy Incoletti 2013-03-25 11:50
Quoting Joe Hildreth:
If I create a custom form field, can I pass data to the getInput() function?

You can't pass data to the getInput function, but extending the preprocessForm method of the model (http://api.joomla.org/11.4/Joomla-Platform/Application/JModelForm.html#methodpreprocessForm) you can perform any kind of modification to your field.
Quote
 
 
#3 Fabio 2013-04-14 14:47
Thank you very much! I became crazy to find out how to redirect to the correct "list view" after saving. I didn't know it needed to have same word (single/plural) !
Quote
 
 
#4 Hardik 2013-04-22 14:52
how can i show inserted user or person list on front-end(using site/registry.p hp)..???
Quote
 
 
#5 dave 2013-05-31 05:22
How can I process the form after either of the buttons save or save and close is clicked?? I need to combine a time field and am/pm field with a date field to save as a time/date value. There is a 'date' field in the db but the other 2 fields (time and am/pm) are only in the form.

I thought I could to this form postprocessing in the prepareTable method, but only the fields which are going to be written to the db seem to be available rather than all the fields in the form.

I then thought I could postprocess in a submitbutton.js but the Joomla.submitbu tton in my file does not get processed.
Quote
 
 
#6 Edy Incoletti 2013-05-31 08:26
Quoting dave:
I thought I could to this form postprocessing in the prepareTable method, but only the fields which are going to be written to the db seem to be available rather than all the fields in the form.

You're absolutely right: prepareTable is the right place to perform such things. You can retrieve additional fields by using the JRequest::getVa r($name) command.
Quote
 
 
#7 Bhautik Radiya 2013-12-15 21:16
give me idea about image upload
Quote
 
 
#8 adam 2017-07-19 10:57
Finally, somewhere that explains the code in the example.

I was looking for an explanation of what loadForm() does and I found it here
Quote