Actions

User

Rvsjoen/tutorial/Developing an MVC Component/Part 13

From Joomla! Documentation

< User:Rvsjoen‎ | tutorial/Developing an MVC Component

Contents

Adding component options

If we want our component to be configurable, then we have to go ahead and add some options, we can add options on several levels. Menu items may have options, the component may have options or the individual items (greetings in our case) may have their own set of options. In this part we will cover how to implement global component options, and how to be able to override them with item-specific options for more granularity. Options are also knows as parameters.

Adding the configuration XML

The component-wide options are defined in their own XML file in the administrator part of your component, so in order to implement these features we need a config.xml file with at least one field in it.

With your favorite editor, create the following file

admin/config.xml

<?xml version="1.0" encoding="utf-8"?>
<config>
        <fieldset
                name="greetings"
                label="COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_LABEL"
                description="COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_DESC">
                <field
                        name="show_category"
                        type="radio"
                        label="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL"
                        description="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC"
                        default="0">
                        <option value="0">JHIDE</option>
                        <option value="1">JSHOW</option>
                </field>
        </fieldset>
</config>

Adding parameters to the database

While the previous XML configuration file pretty much takes care of the "global" component options, in order to support a bit more granularity and use the parameters in Joomla! on a per-item basis we need to add a field to our table in the database.

With your favorite editor, modify the following file to look like this

admin/sql/install.mysql.utf8.sql

DROP TABLE IF EXISTS `#__helloworld`;
 
CREATE TABLE `#__helloworld` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `greeting` varchar(25) NOT NULL,
  `catid` int(11) NOT NULL DEFAULT '0',
  `params` TEXT NOT NULL DEFAULT '',   PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
 
INSERT INTO `#__helloworld` (`greeting`) VALUES
        ('Hello World!'),
        ('Good bye World!');

NOTE: You WILL need to completely uninstall and reinstall the component for these changes to take effect if you have any of the previous parts installed.

Update the editing view

We are going to have to modify our helloworld form in order to add a fieldset for the parameters so they can be edited by the user when editing the items. And afterwards we have to update the edit view template so that the newly added fieldset is displayed to the user.

With your favorite editor, modify the following filer to look like this

admin/models/forms/helloworld.xml

<?xml version="1.0" encoding="utf-8"?>
<form addrulepath="/administrator/components/com_helloworld/models/rules">
        <fieldset name="details">
                <field
                        name="id"
                        type="hidden"
                />
                <field
                        name="greeting"
                        type="text"
                        label="COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_LABEL"
                        description="COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_DESC"
                        size="40"
                        class="inputbox validate-greeting"
                        validate="greeting"
                        required="true"
                        default=""
                />
                <field
                        name="catid"
                        type="category"
                        extension="com_helloworld"
                        class="inputbox"
                        default=""
                        label="COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_LABEL"
                        description="COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_DESC"
                        required="true">
                        <option value="0">JOPTION_SELECT_CATEGORY</option>
                </field>
        </fieldset>
        <fields name="params">
                <fieldset name="params" label="JGLOBAL_FIELDSET_DISPLAY_OPTIONS">
                        <field
                                name="show_category"
                                type="list"
                                label="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL"
                                description="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC"
                                default="">
                                <option value="">JGLOBAL_USE_GLOBAL</option>
                                <option value="0">JHIDE</option>
                                <option value="1">JSHOW</option>
                        </field>
                </fieldset>
        </fields>
</form>

admin/views/helloworld/tmpl/edit.php

<?php
// No direct access to this file
defined('_JEXEC') or die;
 
JHtml::_('behavior.tooltip');
JHtml::_('behavior.formvalidation');
$params = $this->form->getFieldsets('params');
?>
<form action="<?php echo JRoute::_('index.php?option=com_helloworld&layout=edit&id='.(int) $this->item->id); ?>" 
        method="post" name="adminForm" id="helloworld-form" class="form-validate">
        <div class="width-60 fltlft">
                <fieldset class="adminform">
                <legend><?php echo JText::_( 'COM_HELLOWORLD_HELLOWORLD_DETAILS' ); ?></legend>
                <ul class="adminformlist">
                        <?php foreach($this->form->getFieldset('details') as $field): ?>
                                <li><?php echo $field->label;echo $field->input;?></li>
                        <?php endforeach; ?>
                </ul>
                </fieldset>
        </div>
        <div class="width-40 fltrt">
                <?php echo JHtml::_('sliders.start', 'helloworld-slider'); ?>
                <?php foreach ($params as $name => $fieldset): ?>
                        <?php echo JHtml::_('sliders.panel', JText::_($fieldset->label), $name.'-params');?>
                        <?php if (isset($fieldset->description) && trim($fieldset->description)): ?>
                                <p class="tip"><?php echo $this->escape(JText::_($fieldset->description));?></p>
                        <?php endif;?>
                        <fieldset class="panelform" >
                                <ul class="adminformlist">
                                        <?php foreach ($this->form->getFieldset($name) as $field) : ?>
                                                <li><?php echo $field->label; ?><?php echo $field->input; ?></li>
                                        <?php endforeach; ?>
                                </ul>
                        </fieldset>
                <?php endforeach; ?>
                <?php echo JHtml::_('sliders.end'); ?>
        </div>
 
        <div>
                <input type="hidden" name="task" value="helloworld.edit" />
                <?php echo JHtml::_('form.token'); ?>
        </div>
</form>

Updating the toolbar

Now, in order to make the component options available to the user so they can be configured, we need to add an Options button to the toolbar.

With your favorite editor, modify the following files to look like this

admin/views/helloworlds/view.html.php

  1. // No direct access to this file
    
  2. defined('_JEXEC') or die;
    
  3.  
    
  4. jimport('joomla.application.component.view');
    
  5.  
    
  6. class HelloWorldViewHelloWorlds extends JView
    
  7. {
    
  8.         function display($tpl = null) 
    
  9.         {
    
  10.                 // Get data from the model
    
  11.                 $items = $this->get('Items');
    
  12.                 $pagination = $this->get('Pagination');
    
  13.  
    
  14.                 // Assign data to the view
    
  15.                 $this->items = $items;
    
  16.                 $this->pagination = $pagination;
    
  17.  
    
  18.                 // Set the toolbar
    
  19.                 $this->addToolBar();
    
  20.  
    
  21.                 // Display the template
    
  22.                 parent::display($tpl);
    
  23.  
    
  24.                 // Set the document
    
  25.                 $this->setDocument();
    
  26.         }
    
  27.  
    
  28.         protected function addToolBar() 
    
  29.         {
    
  30.                 JToolBarHelper::title(JText::_('COM_HELLOWORLD_MANAGER_HELLOWORLDS'), 'helloworld');
    
  31.                 JToolBarHelper::deleteListX('', 'helloworlds.delete');
    
  32.                 JToolBarHelper::editListX('helloworld.edit');
    
  33.                 JToolBarHelper::addNewX('helloworld.add');
    
  34.                 JToolBarHelper::preferences('com_helloworld');
    
  35.         }
    
  36.  
    
  37.         protected function setDocument() 
    
  38.         {
    
  39.                 $document = JFactory::getDocument();
    
  40.                 $document->setTitle(JText::_('COM_HELLOWORLD_ADMINISTRATION'));
    
  41.         }
    
  42. }
    

Updating the table to support parameters

In the database table, params are stored as JSON-encoded strings, in order to make this transparent to the model, we override the bind() and load() functions of the JTable instance to perform the conversion between a JRegistry object and a JSON-encoded string automatically.

admin/tables/helloworld.php

// No direct access to this file
defined('_JEXEC') or die;
 
jimport('joomla.database.table');
 
class HelloWorldTableHelloWorld extends JTable
{
        function __construct(&$db) 
        {
                parent::__construct('#__helloworld', 'id', $db);
        }
 
        public function bind($array, $ignore = '') 
        {
                if (isset($array['params']) && is_array($array['params'])) 
                {
                        // Convert the params field to a string.
                        $parameter = new JRegistry;
                        $parameter->loadArray($array['params']);
                        $array['params'] = (string)$parameter;
                }
                return parent::bind($array, $ignore);
        }
 
        public function load($pk = null, $reset = true) 
        {
                if (parent::load($pk, $reset)) 
                {
                        // Convert the params field to a registry.
                        $params = new JRegistry;
                        $params->loadJSON($this->params);
                        $this->params = $params;
                        return true;
                }
                else
                {
                        return false;
                }
        }
}

Updating the frontend

Now, at this point, the frontend HelloWorldModelHelloWorld knows nothing about the parameters in the table, or in the component options, so we have to write some more code to make it aware of this. When loading an item from the database we will also convert the JSON-encoded parameters to a JRegistry object, and merge them with the component options. This ensures that the item-specific options can override the component-wide options if they are set.

With your favorite editor, modify the following files to look like this

site/models/helloworld.php

<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
 
jimport('joomla.application.component.modelitem');
 
class HelloWorldModelHelloWorld extends JModelItem
{
        protected $item;
 
        protected function populateState() 
        {
                $app = JFactory::getApplication();
                // Get the message id
                $id = JRequest::getInt('id');
                $this->setState('message.id', $id);
 
                // Load the parameters.
                $params = $app->getParams();
                $this->setState('params', $params);
                parent::populateState();
        }
 
        /**
         * Get the message
         * @return string The message to be displayed to the user
         */
        public function getItem() 
        {
                if (!isset($this->item)) {
                        $id = $this->getState('message.id');
                        $this->_db->setQuery($this->_db->getQuery(true)
                                ->from('#__helloworld as h')
                                ->leftJoin('#__categories as c ON h.catid = c.id')
                                ->select('h.greeting, h.params, c.title as category')
                                ->where('h.id=' . (int)$id));
                        if (!$this->item = $this->_db->loadObject()) {
                                $this->setError($this->_db->getError());
                        } else {
                                // Load the JSON string
                                $params = new JRegistry;
                                $params->loadJSON($this->item->params);
                                $this->item->params = $params;
 
                                // Merge global params with item params
                                $params = clone $this->getState('params');
                                $params->merge($this->item->params);
                                $this->item->params = $params;
                        }
                }
                return $this->item;
        }
}

The frontend view also needs to be updated in order to support only displaying the category if the item is configured to show the category.

With your favorite editor, modify the following files to look like this

site/views/helloworld/tmpl/default.php

// No direct access to this file
defined('_JEXEC') or die;
 
?>
<h1>
        <?php echo $this->item->greeting; ?>
        <?php if($this->item->category && $this->item->params->get('show_category')): ?>
                <?php echo ' ('.$this->item->category.') '; ?>
        <?php endif; ?>
</h1>

Update the language files

With your favorite editor, modify the following files to look like this

admin/language/en-GB/en-GB.com_helloworld.ini

COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_DESC="This message will be displayed"
COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_LABEL="Message"
COM_HELLOWORLD_HELLOWORLD_HEADING_GREETING="Greeting"
COM_HELLOWORLD_HELLOWORLD_HEADING_ID="ID"
COM_HELLOWORLD_HELLOWORLD_DETAILS="Details"
COM_HELLOWORLD_MANAGER_HELLOWORLDS="HelloWorld manager"
COM_HELLOWORLD_MANAGER_HELLOWORLD_NEW="HelloWorld manager: New Message"
COM_HELLOWORLD_MANAGER_HELLOWORLD_EDIT="HelloWorld manager: Edit Message"
COM_HELLOWORLD_N_ITEMS_DELETED_1="One message deleted"
COM_HELLOWORLD_N_ITEMS_DELETED_MORE="%d messages deleted"
COM_HELLOWORLD_ADMINISTRATION="HelloWorld - Administration"
COM_HELLOWORLD_HELLOWORLD_CREATING="HelloWorld - Creating"
COM_HELLOWORLD_HELLOWORLD_EDITING="HelloWorld - Editing"
COM_HELLOWORLD_SUBMENU_MESSAGES="Messages"
COM_HELLOWORLD_SUBMENU_CATEGORIES="Categories"
COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_DESC="The category the messages belongs to"
COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_LABEL="Category"
COM_HELLOWORLD_ADMINISTRATION_CATEGORIES="HelloWorld - Categories"
COM_HELLOWORLD_CONFIGURATION="HelloWorld Configuration"
COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_LABEL="Messages settings"
COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_DESC="Settings that will be applied to all messages by default"
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL="Show category"
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC="If set to Show, the title of the message&rsquo;s category will show."

Installation manifest

In the installation manifest, we have updated the version number and added config.xml

helloworld.xml

<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="2.5.0" method="upgrade">
 
        <name>COM_HELLOWORLD</name>
        <!-- The following elements are optional and free of formatting constraints -->
        <creationDate>June 2011</creationDate>
        <author>John Doe</author>
        <authorEmail>john.doe@example.org</authorEmail>
        <authorUrl>http://www.example.org</authorUrl>
        <copyright>Copyright Info</copyright>
        <license>License Info</license>
        <!--  The version string is stored in the components table -->
        <version>0.0.13</version>
        <!-- The description is optional and defaults to the name -->
        <description>COM_HELLOWORLD_DESCRIPTION</description>
 
        <install>
                <sql>
                        <file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
                </sql>
        </install>
        <uninstall>
                <sql>
                        <file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
                </sql>
        </uninstall>
 
        <!-- Note the folder attribute: This attribute describes the folder
                to copy FROM in the package to install therefore files copied
                in this section are copied from "site/" in the package -->
        <files folder="site">
                <filename>index.html</filename>
                <filename>helloworld.php</filename>
                <filename>controller.php</filename>
                <folder>views</folder>
                <folder>models</folder>
                <folder>language</folder>
        </files>
 
        <media destination="com_helloworld" folder="media">
                <filename>index.html</filename>
                <folder>images</folder>
                <folder>js</folder>
        </media>
 
        <administration>
                <menu img="../media/com_helloworld/images/tux-16x16.png">COM_HELLOWORLD_MENU</menu>
                <submenu>
                        <menu view="helloworlds">COM_HELLOWORLD_SUBMENU_MESSAGES</menu>
                        <menu link="option=com_categories&amp;view=categories&amp;extension=com_helloworld">COM_HELLOWORLD_SUBMENU_CATEGORIES</menu>
                </submenu>
                <!-- Note the folder attribute: This attribute describes the folder
                        to copy FROM in the package to install therefore files copied
                        in this section are copied from "admin/" in the package -->
                <files folder="admin">
                        <filename>index.html</filename>
                        <filename>helloworld.php</filename>
                        <filename>controller.php</filename>
                        <filename>config.xml</filename>
                        <folder>sql</folder>
                        <folder>tables</folder>
                        <folder>models</folder>
                        <folder>views</folder>
                        <folder>language</folder>
                        <folder>controllers</folder>
                        <folder>helpers</folder>
                </files>
        </administration>
 
</extension>

Testing your component

For details on how to install the component into your Joomla! site, refer to the information provided in Part 01.


File listing

Download this part

Download example package

Articles in this series

This tutorial is supported by the following versions of Joomla!

Joomla 2.5